2 糟糕的设计
单以现有的需求而论,上面的设计已经基本能够满足客户的要求。例如,我们创建一个Equipment对象,它包含一个Machine对象,以及两个Port对象,一个为Input类型,一个为Output类型。
Machine machine = new Machine("InputOutputMachine");
![]()
![]()
![]()
Port inputPort = new InputPort();
![]()
Port outputPort = new OutputPort();
![]()
Equipment eqp = new Equipment();
![]()
![]()
![]()
eqp.Name = machine.Name;
![]()
eqp.PortType = "InputOutput";
![]()
![]()
![]()
eqp.AddPort(inputPort);
![]()
eqp.AddPort(outputPort);
![]()
然而,这样的实现存在以下三个明显的缺陷:
— 创建过程过于繁杂,不便于调用方调用;
— Port对象的添加过程无法控制;
— 过于僵化,不利于程序的扩展。
事实上,每当我们创建一个Equipment对象时,都需要执行与上面实现相似的代码。既然如此,我们可以将这样的创建职责进行封装,以便于程序的重用。我们首先想到的是工厂模式。既然是创建三种Equipment对象,利用简单工厂模式即可,例如,定义一个类SimpleLCDFactory。
public static class SimpleLCDFactory
![]()
...{
![]()
public static Equipment CreateInputEQP(string eqpName)
![]()
...{
![]()
Machine machine = new Machine("InputMachine");
![]()
Port inputPort = new InputPort();
![]()
![]()
![]()
Equipment eqp = new Equipment();
![]()
eqp.Name = machine.Name;
![]()
eqp.PortType = "Input";
![]()
![]()
![]()
eqp.AddPort(inputPort);
![]()
}
![]()
public static Equipment CreateOutputEQP(string eqpName)
![]()
...{
![]()
Machine machine = new Machine("OutputMachine");
![]()
Port outputPort = new OutputPort();
![]()
![]()
![]()
Equipment eqp = new Equipment();
![]()
eqp.Name = machine.Name;
![]()
eqp.PortType = "Output";
![]()
![]()
![]()
eqp.AddPort(outputPort);
![]()
}
![]()
public static Equipment CreateIOPutEQP(string eqpName)
![]()
...{
![]()
Machine machine = new Machine("InputOutputMachine");
![]()
Port inputPort = new InputPort();
![]()
Port outputPort = new OutputPort();
![]()
![]()
![]()
Equipment eqp = new Equipment();
![]()
eqp.Name = machine.Name;
![]()
eqp.PortType = "InputOutput";
![]()
![]()
![]()
eqp.AddPort(inputPort);
![]()
eqp.AddPort(outputPort);
![]()
}
![]()
}
![]()
这样一来,要创建一个Equipment对象就相对容易多了。
Equipment eqp = SimpleLCDFactory.CreateIOPutEQP("InputOutputMachine");
由于提供了专门的方法来创建Equipment对象,之前提到的前两个缺陷就被有效地克服了。然而,由于采用的简单工厂模式并没有将可能存在的创建变化进行抽象,导致这样的结构仍然僵化,不易于扩展。例如,在增加一个新的Equipment对象组合时,就需要在SimpleLCDFactory类中添加一个新的方法创建这个对象。
要支持未来需求可能的变化,也可以引入Factory Method模式,将创建Equipment对象的方法进行抽象,具体的实现留待各自的实现子类来完成。坦白说,这未尝不是一个好的实现方案。然而,考虑到这里要创建的Equipment对象,是由Port对象和Machine对象组成的,我们关注的创建行为,归根结底,是如何将Port对象和Machine对象创建好,并使之组合成我们需要的整体对象Equipment,因此,采用Builder模式也许是更好的选择。
注意:实际上,Factory Method模式与Builder模式并没有泾渭分明的区别,尤其针对Builder模式,可以将其转换为Factory Method模式,反之则不然。
也就是说,Factory Method模式的应用更加广泛。如果一定要做出区分,那么可以说,二者同时生成产品,Factory Method模式主要用于生成一类完整的产品,而Builder模式则更关注于产品内部各种零件的组合,并最终组装为整体的产品。由于Builder模式对产品内部的创建进行了细分,因此对于那些内部具有一定结构的目标对象,如本例的Equipment,非常好的选择仍然是Builder模式。![]()
