软件开发中应该注意的事情有两点:
1.多组合少继承
继承虽说能简化代码,提高一定的复用性,但是对与代码耦合度影响较大
2.多扩充少修改
因新需求扩充新功能,而少修改已经通过测试的程式码。
 
今天要介绍的就是组合模式,一种提供整体与部分的对照。这种理论很像树形,例如树中有树枝和树叶,树枝上有树叶,可以把树叶看做子节点
,那么树枝也可以看成一个节点,但是这个节点和叶子节点的不同之处在于,其有子节点。另一个
例子就是,公司中各个部门和群组
然后处理相关
商业需求逻辑,好比报表显示、读取资料...等,
大多Client端可能要先依输入资料取得相对应部门物件,
这里面可能也有部门群组的判断处理(如处别又是另一种
商业逻辑),
而且部门群组的异动也将会造成Client端程式码频繁修改,
导致Client端的耦合性很高、不容易维护...等,
为了将Client程式码解耦,我们透过组合模式,将物件组合成为简单层次结构,
让Client端可以使用一致的方法来处理组合物件就像处理个别物件一样(将一对多改为一对一),
并且自己可以处理自己复杂的商业逻辑,
下面我们实际来看一下组合模式可以帮Client程式码带来
什么样的改善。
 
 
需求:依照部门处理相关商业逻辑
 
大多数人可能会这样写Client端程式码
String [] Departments={"DepA" ,"DepB","DepC","DepAll"}
Factory defactory=new Factory();
for(String depart in Departments)
{
  IDepProcess mydep=depfactory.getDep(depart);
   if (mydep is DepartmentA ) //单部门
                 {
                     //读资料
                     mydep . Process();
                }
                else if (mydep is DepartmentB )
                {
                    //更新资料
                     mydep . Process();
                }
                else if (mydep is DepartmentC )
                {
                    //删除资料
                     mydep . Process();
                }
                else if (mydep is DepartmentGroup ) //部门群组
                 {
                     //处别的处理
                    //先确认各部门人数..等
                    mydep . Process();
                     List < IDepProcess > mydeps = (mydep as DepartmentGroup ) . GetDepartments();
                     foreach ( IDepProcess dep in mydeps)
                    {
                        //if(dep is DepartmentA)....
                        //Client继续处理相关判断
                    }
                }
            }
			
			
	public 
class Factory
     {
         public Factory() { }
        public IDepProcess GetDep( string Department)
        {
            IDepProcess _IDepProcess = null ;
             switch (Department)
            {
                case "DepA" :
                    _IDepProcess = new DepartmentA (); 
                     
break ;
                 case "DepB" :
                    _IDepProcess = new DepartmentB (); 
                     break ;
                 case "DepC" :
                    _IDepProcess = new DepartmentC (); 
                     break ;
                 case "DepAll" :
                    _IDepProcess = new DepartmentGroup ();
                     break ;
                 default :
                    _IDepProcess = new DepartmentA (); 
                     break ;            
            }
            return _IDepProcess;
        }    
    }
 
接口
 
 public interface IDepProcess
     {
         void Process();       
    }
 
public class DepartmentA  extends  IDepProcess
     {
        #region IDepProcess成员
        public void Process()
        {
            System.out.println( "部门A处理" );
        }
        #endregion
     }
    public class DepartmentB extends IDepProcess
     {
        #region IDepProcess成员
        public void Process()
        {
             System.out.println( "部门B处理" );
        }
        #endregion
     }
    public class DepartmentC extends IDepProcess
     {
        #region IDepProcess成员
        public void Process()
        {
             System.out.println( "部门C处理" );
        }
        #endregion
     }
    public class DepartmentGroup extends IDepProcess
     {
         protected List < IDepProcess > departments = new List < IDepProcess > ();
         public List < IDepProcess > GetDepartments()
        {
          return departments;
        }
        #region IDepProcess成员
        public void Process()
        {
            System.out.println( "组合部门处理" );
        }
        #endregion
     }
	 
	 
接下来使用组合模式来重构Client程式码
            IDepProcess mydep = new DepartmentGroup (); 
            mydep . Add( new DepartmentA ());
            mydep . Add( new DepartmentB ()); 
            mydep . Add( new DepartmentC ()); 
            mydep . Process();
 
 
修改组合模式中抽象接口,用处叶子节点和组合节点
     public interface IDepProcess
     {
         void Process();
         void Add( IDepProcess DepProcess);
         void Remove( IDepProcess DepProcess);
    }
 
 
为了要处理子物件逻辑,所以增加2各方法(Add、Remove)
 
其他类别修改如下
 public class DepartmentA extends IDepProcess
     {
        #region IDepProcess成员
        public void Process()
        {
            System.out.println( "部门A处理" );
        }  
        public void Add( IDepProcess DepProcess)
        {
             throw new Unsupported
OperationException("对象不支持这个功能");;
        }
        public void Remove( IDepProcess DepProcess)
        {
             throw new UnsupportedOperationException("对象不支持这个功能");
        }
        #endregion
     }
 
Add 和Remove 对于没有子部门(最底层)类别来说没有任何
意义,所以抛出
自定义讯息。
 
群组类别修改如下
 public class DepartmentGroup extends IDepProcess
     {     
         protected List < IDepProcess > departments = new List < IDepProcess > ();
        #region IDepProcess成员
        public void Add( IDepProcess DepProcess)
        {
            departments . Add(DepProcess);
        }
        public void Remove( IDepProcess DepProcess)
        {
            departments . Remove(DepProcess);
        }      
        public void Process()
        {
            System.out.println( "组合部门处理" );       
             if (departments . Count > 0 )
            {
                foreach ( IDepProcess dep in departments)
                {
                    dep . Process(); //可能是子部门或其他部门
                 }
            }
        }
        #endregion       
     }
 
 
 
从应用角度来看,如果你想把一对多的关系,转换为一对一的关系(一致性的行为),
那么你可以看到组合模式所带来的好处。