The document discusses the Law of Demeter principle of low coupling between objects. It provides examples of code that violates the Law of Demeter by traversing object relationships more than one level deep. The document then presents solutions to avoid these violations by introducing action classes that allow applying operations directly to rooms and lamps without traversing relationships.
9. Law of Demeter
IFloorLampPolicy
+evaluate(is_day: bool)
+get_floor(): IFloor
+set_floor(floor: IFloor)
~ floor_: IFloor
class IFloorLampPolicy:
def evaluate(self, is_day: bool):
pass
class CurfewPolicy(IFloorLampPolicy):
def evaluate(self, is_day: bool):
if is_day:
return
# Turn all light off in the floor
for room in self.get_floor().get_rooms():
for _, lamps in room.get_lamps().items():
for lamp in lamps:
lamp.set_color(white)
lamp.set_intensity(0)
CurfewPolicy
10. Law of Demeter
IFloorLampPolicy
+evaluate(is_day: bool)
+get_floor(): IFloor
+set_floor(floor: IFloor)
~ floor_: IFloor
class IFloorLampPolicy:
def evaluate(self, is_day: bool):
pass
class CurfewPolicy(IFloorLampPolicy):
def evaluate(self, is_day: bool):
if is_day:
return
# Turn all light off in the floor
for room in self.get_floor().get_rooms():
for _, lamps in room.get_lamps().items():
for lamp in lamps:
lamp.set_color(white)
lamp.set_intensity(0)
CurfewPolicy
Law of Demeter violation (High Coupling):
get_floor() -> get_rooms() -> get_lamps()
12. Law of Demeter violation problems
IFloor
constructor(rooms: [IRoom])
+get_rooms(): [IRoom]
~ rooms_: [IRoom]
IFloor
constructor(rooms: [IRoom], corridor: IRoom)
+get_rooms(): [IRoom]
+get_corridor(): IToom
~ rooms_: [IRoom]
~ corridor_: IRoom
class IFloorLampPolicy:
def evaluate(self, is_day: bool):
pass
class CurfewPolicy(IFloorLampPolicy):
def evaluate(self, is_day: bool):
if is_day:
return
# Turn all light off in the floor
for room in self.get_floor().get_rooms():
for _, lamps in room.get_lamps().items():
for lamp in lamps:
lamp.set_color(white)
lamp.set_intensity(0)
13. Law of Demeter violation problems
IFloor
constructor(rooms: [IRoom])
+get_rooms(): [IRoom]
~ rooms_: [IRoom]
IFloor
constructor(rooms: [IRoom], corridor: IRoom)
+get_rooms(): [IRoom]
+get_corridor(): IToom
~ rooms_: [IRoom]
~ corridor_: IRoom
class IFloorLampPolicy:
def evaluate(self, is_day: bool):
pass
class CurfewPolicy(IFloorLampPolicy):
def evaluate(self, is_day: bool):
if is_day:
return
# Turn all light off in the floor
for room in self.get_floor().get_rooms():
for _, lamps in room.get_lamps().items():
for lamp in lamps:
lamp.set_color(white)
lamp.set_intensity(0)
15. Avoiding Law of Demeter violation
class IRoom:
def apply_action(self, action: ILampAction):
for lamp_type, lamps in self.lamps_.items():
for lamp in lamps:
action.evaluate(lamp)
class IFloor:
def apply_action(self, action: ILampAction):
for room in self.rooms_:
room.apply_action(action)
self.corridor_.apply_action(action)
class CurfewPolicy(IFloorLampPolicy):
def evaluate(self, is_day: bool):
if is_day:
return
floor = self.get_floor()
floor.apply_action(LampOff())
class ILampAction:
def evaluate(self, lamp: ILamp):
pass
class LampOff(ILampAction):
def evaluate(self, lamp: ILamp):
lamp.set_color(white)
lamp.set_intensity(0)
class LampOn(ILampAction):
def evaluate(self, lamp: ILamp):
lamp.set_intensity(100)
class RedLampOff(ILampAction):
def evaluate(self, lamp: ILamp):
if lamp.get_color() == red:
lamp.set_intensity(0)