I'm trying to figure out the best design pattern to insulate a child object from knowing too much about the parent object it is contained in.
For instance, with a parent class like this...
class Airplane { var seats:Array ... function removeSeat(seat:Seat) { // find seat object in seats array and remove it 开发者_如何学编程 } }
child class...
class Seat { var rowNumber:int ... }
If I'm working in the context of the Seat object and I want to remove myself from my parent Airplane object, what is the best way of separating the Seat from knowing about where it is in the Airplane.seats array?
I know I can pass the Airplane parent object into the constructor of the Seat, then call the removeSeat method on Airplane to remove that Seat, but I want to the Seat knowing as little about the Airplane if possible. Any ideas?
You could use the event handler pattern - essentially the airplane passes a 'removeMe' callback into the Seat on construction. The Seat then executes this callback when it wants to be removed. The seat has no idea who passed in the callback - it just needs to know the signature of the callback, in this example that the first parameter is a reference to a Seat object.
E.g. in pseudo-code
class Airplane {
// will be passed in as callback
function removeSeat(seat) {
array.remove(seat);
}
..
var seat = new Seat();
seat.removeCallback = removeSeat;
..
}
class Seat() {
removeCallback = null;
...
...
// when we want to remove the seat, run the callback if set
if (removeCallback !== null) {
removeCallback(this);
}
}
Try implementing a variation of the Visitor pattern.
interface SeatContainer {
function removeSeat(seat:Seat);
}
Then your airplane implements the interface
class Airplane implements SeatContainer {
var seats:Array
...
function removeSeat(seat:Seat) {
// find seat object in seats array and remove it
}
}
And your seat hold a reference to the interface
class Seat {
var container:Container
...
function removeMyself() {
container.removeSeat(this);
}
}
This way, the Seat object ignores what kind of container is in, being isolated of the actual implementation of the SeatContainer: it could be a Car, a Cinema, a Boat, or whatever implementation of SeatContainer interface.
In order to keep this separation, the context where you access seats should also know witch airplane they belong. Ex:
class AirplaneService {
public function removeEmptySeats(Airplane airplane) {
foreach seat in airplane {
if seat is empty {
airplane.removeSeat(seat);
}
}
}
public function removeRowSeats(Airplane airplane, int rowNumber) {
foreach seat in airplane {
if seat.getRowNumber() == rowNumber {
airplane.removeSeat(seat);
}
}
}
}
精彩评论