一、动机(Motivation)问题域在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?二、意图(Intent) 解决方案使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。三、结构(Structure)UML<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
四、代码(Code)
public class Game { public static void Run() { NormalActor na1 = new NormalActor(); NormalActor na2 = new NormalActor(); NormalActor na3 = new NormalActor(); NormalActor na4 = new NormalActor(); NormalActor na5 = new NormalActor(); FlyActor fa1 = new FlyActor(); FlyActor fa2 = new FlyActor(); } } // 步兵 public class NormalActor {} // 飞行兵 public class FlyActor {} // 重构1 public abstract AbstractNormalActor {} public abstract AbstractFlyActor {} public class Game { public static void Run() { AbstractNormalActor na1 = new NormalActor(); AbstractNormalActor na2 = new NormalActor(); AbstractNormalActor na3 = new NormalActor(); AbstractNormalActor na4 = new NormalActor(); AbstractNormalActor na5 = new NormalActor(); AbstractFlyActor fa1 = new FlyActor(); AbstractFlyActor fa2 = new FlyActor(); } } // 重构2 public class Game { public static void Run(AbstractNormalActor na,AbstractFlyActor fa) { AbstractNormalActor na1 = na.clone(); AbstractNormalActor na2 = na.clone(); AbstractNormalActor na3 = na.clone(); AbstractNormalActor na4 = na.clone(); AbstractNormalActor na5 = na.clone(); AbstractFlyActor fa1 = fa.clone(); AbstractFlyActor fa2 = fa.clone(); } } public abstract AbstractNormalActor { public abstract AbstractNormalActor clone();} public abstract AbstractFlyActor { public abstract AbstractFlyActor clone();} // 步兵 public class NormalActor { public override AbstractNortalActor clone() { return (AbstractNortalActor)this.MemberwiseClone(); }} // 飞行兵 public class FlyActor { public override AbstractFlyActor clone() { return (AbstractFlyActor)this.MemberwiseClone(); }} 现在Game仅仅依赖于抽象类而不依赖于具体实现类了 class App { void main() { AbstractNormalActor ana = new NormalActor(); AbstractFlyActor afa = new FlyActor(); Game.Run(ana,afa); }}注:MemberwiseClone()方法是.net framework默认实现,是浅拷贝。对于值类型没有问题,但对于引用类型就会出现两个对象共用一个引用值的问题了,因为它们是克隆了引用类型的地址。所以引用类型的值相同。解决这个问题之一是实现深度拷贝,如new一个对象,把当前对象的字段值一个一个赋给新的new对象。或者通过序列化的方式来做,这是一个取巧的过程。我们假设上面的AbstractNormalActor和AbstractFlyActor不可以进行抽象了,是不同的对象。五、Prototype模式的要点Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非灵活地动态创建“拥有某些稳定接口”的新对象------所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方不断地Clone。Prototype模式中的Clone方法可以利用.net中的Object类的MemberwiseClone()方法或者序列化来实现深拷贝。六、创建型模式的总结1.Singleton模式解决的是实体对象个数的问题。除了Singleton之外,其他创建型模式解决的都是New所带来的耦合关系。2.Factory Method,Abstract Factory,Builder都需要一个额外的工厂类来负责实例化易变对象,而Prototype则是通过原型(一个特殊的工厂类)来克隆易变对象。3.如果遇到“易变类”,起初的设计通过从Factory Method开始,当遇到更多的复杂变化时,再考虑重构为其它三种工厂模式(Abstract Factory,Builder,Prototype)。有关更多的Factory Method,Abstract Factory,Builder之间的区别请看Builder模式一讲,原则上来讲Abstract Factory,Prototype可以相互替换,但如果用Prototype替换Abstract Factory,那么需要创建的对象应该是很容易克隆才行,最好是能用MemberwiseClone()方法,否则显示太复杂,不划算,但理论上是可行的。
转载于:https://www.cnblogs.com/hotsoho.net/articles/348069.html
相关资源:JAVA上百实例源码以及开源项目