Composite组合(结构型模式)

mac2022-06-30  19

问题在面向对象系统中,我们常会遇到一类具有“容器”特征的对象---即它们在充当对象的同时,又是其他对象的容器。动机上述描述的问题根源在于:客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等弊端。如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?意图将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。代码public interface IBox{  void Process();}public class SingleBox:IBox{  public void Process()  {    ...  }}public class ContainerBox:IBox{   public void Process(){}   public ArrayList GetBoxes(){}}public class App{  public static void Main()  {     IBox box = Factory.GetBox();     if(box is ContainerBox)     {       //问题:客户代码与对象内部结构耦合太紧       box.Process();       ArrayList list = ((ContrainerBox)box)GetBoxes();       //接下来将面临比较复杂的递归处理     }     else     {       box.Process();     }  }}改进...(客户代码仅与抽象接口耦合)public class App{  public static void Main()  {     IBox box = Factory.GetBox();     box.Process();  }}public class ContainerBox:IBox{    ArrayList list = null;    public void Add(IBox box)    {       if(list == null)        {            list = new ArrayList();        }       else{           list.Add(box);       }    }   public void Remove(IBox box)   {      if(list == null)      {        throw new Excepion();      }      list.Remove(box);   }   public void Process()   {     //1.do something...

     //2.do process for the box in the list     if(list != null)     {          foreach(IBox box in list)          {             box.Process(); //其实是递归调用           }     }   }}改进...(统一处理SingleBox和ContrainerBox)public interface IBox{  void Process();  void Add(IBox box);  void Remove(IBox box);}public class SingleBox:IBox{  public void Process()  {    ...  }  public void Add(IBox box)  {    //抛出异常   }  public void Remove(IBox)  {    //抛出异常   }}其实就是一个树型结构,SingleBox是叶子结点,ContrainerBox是树枝。其实可以把SingleBox和ContrainerBox都当作是容器。UML要点Composite模式采用树形结构来实现普遍存在的对象容器,从而将一对多的关系转化为一对一的关系,使得客户代码可以一致地处理对象和对象容器,无需关心处理的是单个对象还是组合的对象容器。将“客户代码与复杂的对象容器结构”解耦是Composite模式的核心思想,解耦之后,客户代码将纯粹的抽象接口--而非对象容器的复杂内部实现结构--发生依赖关系,从而更能应对变化。Composite模式中,是将Add和Remove等和对象容器相关的方法定义在表示抽象对象的Component类中,还是将其定义在表示对象容器的Composite类中,是一个关于透明性和安全性的两难问题,需要仔细权衡。这里有可能违背面向对象的单一职责原则,但是对于这种特殊结构,这又是必须付出的代价。Asp.net控件的实现在这方面为我们提供了一个很好的示范。Composite模式在具体实现中,可以让父对象中的子对象反追溯;如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率。

转载于:https://www.cnblogs.com/hotsoho.net/articles/361318.html

最新回复(0)