/* composite模式:
* 使用场景:多层盒子,盒子里面有盒子,最内层的盒子不包含盒子。
*
* 常规思路:
* singleBox:IBox【最内层盒子】,ContainerBox【外层和中间的盒子】
* IBox box = Factory.GetBox();
* if(box is ContainerBox)
* {
* box.process();
* ArrayList list = ((ContainerBox)box).GetBoxes(); //得到ContainerBox的一个数组,然后递归处理这些盒子
* }
* else if(box is singleBox)
* {box.process();}
* 缺点:采用递归处理,客户代码和对象内部结构紧密耦合,当对象内部结构变化时,客户代码要进行大量修改【递归过程改变】。
*
*
* 动机:客户代码过多的依赖于对象容器复杂的内部实现结构【多层组合而来的盒子】,对象容器的内部实现结构的变化将引起客户代码的频繁变动。
*
* 解决方法:让对象容器自己来实现自身的复杂结构,让客户代码就像处理简单对象一样来处理复杂的对象容器。
*
* 意图:将对象组合成树形结构以表示“部分-整体”的层次结构,composite使得用户可以对单个对象和组合对象的使用具有一致性。
*
* UML说明:
* 类:component:IBox, leaf:singleBox, ContainerBox:composite,
* 变量:children:list
*/
public interface IBox
{
void Process();
//本来是在ContainerBox中方法,为了客户程序统一【不需要判断类型】,我们提升到接口中。
//虽然SingleBox不支持这些方法,我们可以通过抛出异常方式实现。
void Add(IBox box);
void Remove(IBox box);
}
public class SingleBox : IBox
{
public void Process()
{
}
public void Add(IBox box) { /* throw Exception;*/ }
public void Remove(IBox box) { /* throw Exception;*/ }
}
public class ContainerBox : IBox
{
ArrayList list = null; //ArrayList应该是存放IBox类型对象的可变长数组
public void Add(IBox box)
{
if (list == null)
list = new ArrayList();
list.Add(box);
}
public void Remove(IBox box)
{
if (list == null)
/* throw Exception;*/
list.Remove(box);
}
public void Process()
{
//对自身做一些处理
//对包含的盒子进行处理(盒子存储在list中)
if (list != null)
foreach (IBox box in list)
box.Process();
}
}
/*composite模式要点:
*将“一对多”的关系转换为“一对一”的关系,即将客户代码处理的一对多转换为一对一的处理。
* 使得客户代码和复杂对象容器结构结构,客户只需关注的是盒子,而不需要关系是SingleBox还是ContainerBox
* Add和Remove方法是放在ContainerBox还是IBox中,各有权衡。如果放在在前者,则客户代码仍需要判断box类型;
* 而放到IBox中,则需要抛出异常,因为IBox类中不应该包含Add和Remove方法,这违背了类的单一职责原则。
*/
class composite
{
static void Main ()
{
IBox box1 = new SingleBox(); // 具体编码中应该采用Factory.GetBox(),即使用创建型模式构建不同类型的对象实例。
IBox box2 = new ContainerBox();
box1.Process();
box2.Process();
}
}