复合模式是SOLID吗?

Omu*_*Omu 11 design-patterns liskov-substitution-principle composite solid-principles interface-segregation-principle

叶在综合模式实现了Component接口,包括Add,Remove,和GetChild方法,一个叶是永远不会使用.这似乎违反了接口隔离原则.

那么复合模式SOLID的用法是什么?

链接到Composite Pattern:http://www.dofactory.com/Patterns/PatternComposite.aspx

Sin*_*hot 11

链接和大多数书中描述的模式中的真实气味是Component具有a的方法Composite.我认为这可能是因为这种模式相当陈旧,并且多年来一直以这种方式重复.我的看法是,只有Composite应该有任何与合成相关的方法.

我曾经将棋盘游戏改为电脑游戏.将棋子放在地球地图上,分成六边形.99%的六边形代表一个位置.不幸的是,一些六边形包含多个位置,例如,一些六边形内部有几个岛.我使用复合模式来表示这些位置,但不是如链接所示.它是这样的(在Java中):

public interface Location {
   Set<Army> getArmies();
}

public class SingleLocation implements Location {

   public Set<Army> getArmies() {
      return armies ;
   }

   private Set<Army> armies = new HashSet<Army>();
}

public class CompositeLocation implements Location {

   public Set<Army> getArmies() {

      Set<Army> armies = new HashSet<Army>();

      for(Location subLocation: subLocations) {
         armies.addAll(subLocation.getArmies());
      }

      return armies;
   }

   public void addSubLocation(Location location) {
      subLocations.add(location);
   }

   private Set<Location> subLocations = new HashSet<Location>();
}
Run Code Online (Sandbox Code Playgroud)

请注意,只有Composite具有合成方法,并且甚至没有向大多数客户端公开它有子项的事实(在此示例中,客户端只需要来自某个位置的军队列表 - 事实上它们位于许多子位置是无关紧要的).

请记住,设计模式不是必须精确实现的.把它们想象成食谱.当你在烹饪时遵循食谱时,你当然可以完全遵循它.然而,一些厨师会在食谱上投入自己的曲折.其他人甚至不会看它,因为他们是专家,可以根据食谱的精神一起扔东西,甚至不用考虑它.设计模式也是如此.它们是可塑性的食谱.

您也可以采用那些SOLID原则.如果您阅读罗伯特·马丁的文章,他表示不经过深思熟虑地应用这些原则会产生过于复杂的代码.软件是通过一系列权衡和平衡设计的 - 有时你放弃纯粹的SOLID,因为它产生更简洁,更简单的代码.如果你要使你的代码完全封装,灵活,解耦等,你将发明一种新的编程语言:-)


ctf*_*ord 7

我会说你链接中描述的复合模式违反了Liskov替换原则,这是五个SOLID原则之一.

Component有一些方法只对一个Composite例子有意义Add().Leaf继承自Component所以它将有一个Add()像任何其他方法Component.但是Leafs没有子节点,因此以下方法调用无法返回有意义的结果:

myLeaf.Add( someChild );

该调用必须抛出一个MethodNotSupportedException,返回null或以其他方式向调用者指示将一个子项添加到a中Leaf是没有意义的.

因此,你不能像对待Leaf任何其他人那样对待,Component因为如果你尝试,你会得到一个例外.Liskov替代原则指出:

设q(x)是关于类型T的对象x可证明的属性.对于类型S的对象y,q(y)应该为真,其中S是T的子类型.

Components拥有可以添加子项的属性.但你不能把孩子添加到a Leaf,即使Leaf是子类型Component,这违反了原则.