吸气剂是否违反得墨忒耳法则?
Do getters violate the Law of Demeter?
假设有一个 GameState
类型使用 GameContext
(通过 process
方法):
abstract class GameState {
public abstract void process(GameContext context);
}
GameContext 将包含诸如玩家、商店等对游戏必不可少的内容。
一个州可以访问它需要的东西:
class CombatState extends GameState {
public void process(GameContext context) {
Player player = context.getPlayer();
if(player.isAlive()) {
//...
}
}
}
语句 player.isAlive()
可以重写为 context.getPlayer().isAlive()
。
我的问题
Demeter 法则指出,对象只能与直系亲属互动。会不会违反原则,如何解决?
对于要动态处理的每个状态,形式参数必须为所有可能的状态所接受。 这使得严格按照对象的需要传递对象变得困难,这就是为什么每个状态都从 "main source" 中获取它需要的东西的原因。我觉得主要来源的凝聚力很低,因为 ShopState
需要的数据与 CombatState
不同
因为定界符法则是松散耦合的一个特例。
我认为它的工作方式是:
我们可以访问特定 class 的字段及其方法,即使我们正在链接多个方法(比方说)。我们一直在java中这样做,需要注意的是,链接仅适用于单个class.
的方法
定界符法则告诫我们不要一次访问多个class对象的and/or方法。
示例:
如果我们有 classes A, B, C.
B class 有一个字段包含 A 的引用,C 有 B 的引用。
那么我们不应该使用 getters 通过 C 获取 A 的引用,它有助于保持松散耦合。
同样,这就是我认为的工作方式。
状态不是过程,过程是过程。战斗是一个过程,活着是一种境界。
使用process
的抽象名称需要打破得墨忒尔定律
看这个例子:
class CombatProcess extends GameProcess {
public void hit(Player puncher, Player beaten) {
if (beaten.getState().isAlive()) {
Weapon oneWeapon = one.getCurrentWeapon();
...
}
}
}
CombatProcess 中的一切都尽可能具体。
分析什么玩家与什么玩家战斗不是 CombatProcess 本身的责任!在 CombatProcess 开始之前,您必须知道您与谁作战。
编辑:
您在本回答的评论中写道:
If I had the states in a Set, List or Map, I would not be able to polymorphically process the states,
这是绝对正确的。 Hook/Anchor-Pattern is from 1996 and still used widely and glory in windows (so called system-hooks)。不幸的是,由于一些批评,它 没有 进入 OOD 的前 10 大模式。其中一位评论家是:
... its not easy to abstract all the operations of a process into logical independent hooks, and to thereafter anchor them and iterate them properly.
我的个人看法是Hook/Ancher-Pattern在1996年是革命性的,将来与CDI(例如spring)的结合将是革命性的。
终于!你可以决定:
- 打破得墨忒耳法则。
- 删除 Hook/Ancher-Pattern。
- 写一个解决方法 here。
假设有一个 GameState
类型使用 GameContext
(通过 process
方法):
abstract class GameState {
public abstract void process(GameContext context);
}
GameContext 将包含诸如玩家、商店等对游戏必不可少的内容。
一个州可以访问它需要的东西:
class CombatState extends GameState {
public void process(GameContext context) {
Player player = context.getPlayer();
if(player.isAlive()) {
//...
}
}
}
语句 player.isAlive()
可以重写为 context.getPlayer().isAlive()
。
我的问题
Demeter 法则指出,对象只能与直系亲属互动。会不会违反原则,如何解决?
对于要动态处理的每个状态,形式参数必须为所有可能的状态所接受。 这使得严格按照对象的需要传递对象变得困难,这就是为什么每个状态都从 "main source" 中获取它需要的东西的原因。我觉得主要来源的凝聚力很低,因为 ShopState
需要的数据与 CombatState
因为定界符法则是松散耦合的一个特例。
我认为它的工作方式是:
我们可以访问特定 class 的字段及其方法,即使我们正在链接多个方法(比方说)。我们一直在java中这样做,需要注意的是,链接仅适用于单个class.
的方法定界符法则告诫我们不要一次访问多个class对象的and/or方法。
示例:
如果我们有 classes A, B, C.
B class 有一个字段包含 A 的引用,C 有 B 的引用。
那么我们不应该使用 getters 通过 C 获取 A 的引用,它有助于保持松散耦合。
同样,这就是我认为的工作方式。
状态不是过程,过程是过程。战斗是一个过程,活着是一种境界。
使用process
的抽象名称需要打破得墨忒尔定律
看这个例子:
class CombatProcess extends GameProcess {
public void hit(Player puncher, Player beaten) {
if (beaten.getState().isAlive()) {
Weapon oneWeapon = one.getCurrentWeapon();
...
}
}
}
CombatProcess 中的一切都尽可能具体。
分析什么玩家与什么玩家战斗不是 CombatProcess 本身的责任!在 CombatProcess 开始之前,您必须知道您与谁作战。
编辑:
您在本回答的评论中写道:
If I had the states in a Set, List or Map, I would not be able to polymorphically process the states,
这是绝对正确的。 Hook/Anchor-Pattern is from 1996 and still used widely and glory in windows (so called system-hooks)。不幸的是,由于一些批评,它 没有 进入 OOD 的前 10 大模式。其中一位评论家是:
... its not easy to abstract all the operations of a process into logical independent hooks, and to thereafter anchor them and iterate them properly.
我的个人看法是Hook/Ancher-Pattern在1996年是革命性的,将来与CDI(例如spring)的结合将是革命性的。
终于!你可以决定:
- 打破得墨忒耳法则。
- 删除 Hook/Ancher-Pattern。
- 写一个解决方法 here。