软件开发中应该注意的事情有两点:
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
}
从应用角度来看,如果你想把一对多的关系,转换为一对一的关系(一致性的行为),
那么你可以看到组合模式所带来的好处。