原型模式(Prototype Pattren)
原型模式用原型实例指定创建对象的种类,而且通过拷贝这些原型创建新的对象。
考试结束了,学校放假了。我们又进入了全职提高班的学习模式:
6:50——起床(当然,年轻人总是爱睡个懒觉,早上总是赖床。有时也会拖到7:00起床)7:20——去中门买早餐带到机房
12:00——回家吃午饭,然后睡午觉
14:30——又開始了下午的学习
18:00——回家吃晚饭。然后去机房
22:00——回家,洗漱然后睡觉
我们就这样日复一日的生活着。仅仅有周四,才干放松一下自己,好好歇息歇息。我们要有理想和目标。那样才干有生活学习的动力!
言归正传。以下我们来看看我们一天的生活和我们今天讲的原型模式有什么关联。从上面能够看出,我们每天的生活是一个循环,什么是循环呢?就是反复相同的动作,用原型模式的概念就是:用原型实例指定创建对象的种类。即我们一天的生活,假设要生成非常多天的生活模式,仅仅要通过赋值这些原型创建信的对象就能够了,而不必每次都要new一个实例对象。
这样将大大节省创建对象所消耗的各种资源。
以下我们就来看看详细怎么实现
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 原型模式 { //原型类 class DayLife:ICloneable { private string getUp; private string getFood; private string noon; private string afternoon; private string dinner; private string goHome; public void setGetUp(string getup) { this.getUp = getup; } public void setGetFood(string getfood) { this.getFood = getfood; } public void setNoon(string noon) { this.noon = noon; } public void setAfternoon(string afternoon) { this.afternoon = afternoon; } public void setDinner(string dinner) { this.dinner = dinner; } public void setGoHome(string gohome) { this.goHome = gohome; } //显示 public void Display() { Console.WriteLine(getUp); Console.WriteLine(getFood); Console.WriteLine(noon); Console.WriteLine(afternoon); Console.WriteLine(dinner); Console.WriteLine(goHome); Console.WriteLine(); } public object Clone() { return (object)this.MemberwiseClone(); } } class Program { static void Main(string[] args) { DayLife a = new DayLife(); a.setGetUp("6:50起床"); a.setGetFood("7:20去中门买早餐带到机房"); a.setNoon("12:00回家吃午饭,然后睡午觉"); a.setAfternoon("14:30又開始了下午的学习"); a.setDinner("18:00回家吃晚饭,然后去机房"); a.setGoHome("22:00回家,洗漱然后睡觉"); a.Display(); DayLife b = (DayLife)a.Clone(); b.setGetUp("早上赖床了,7:00才起床"); b.Display(); } } }
能够看到,仅仅有第一个DayLife对象是通过new创建的,第二个是通过clone克隆生成的。这就是原型模式:通过一个已经存在的对象。利用其现有的条件,克隆生成一个全新的对象。在此基础上改动部分内容。形成全新对象实体!
在原型模式结构图中包括例如以下几个角色:
Prototype(抽象原型类):它是声明克隆方法的接口。是全部详细原型类的公共父类。能够是抽象类也能够是接口,甚至还能够是详细实现类。
ConcretePrototype(详细原型类):它实如今抽象原型类中声明的克隆方法。在克隆方法中返回自己的一个克隆对象。
Client(客户类):让一个原型对象克隆自身从而创建一个新的对象。在客户类中仅仅须要直接实例化或通过工厂方法等方式创建一个原型对象。再通过调用该对象的克隆方法就可以得到多个同样的对象。因为客户类针对抽象原型类Prototype编程,因此用户能够依据须要选择详细原型类,系统具有较好的可扩展性,添加或更换详细原型类都非常方便。
使用原型模式时,我们须要注意:
1.克隆对象时对象的构造方法不运行
一般在使用new操作符创建一个对象的时候。一定会运行类的构造方法,在构造方法中能够做一些数据载入或者初始化的操作。然而,在实现Cloneable接口的类中。重载clone方法产生新对象时,是不会运行类的构造方法的!
2.浅复制和深复制
浅复制:仅仅复制本对象的原始数据类型,如int、float、String等,对于数组和对象引用等是不会复制的。
深复制:不但对原始数据类型做复制,对于对象中的数组和对象引用也做复制的行为,从而达到将对象全然复制的效果。主要长处:
1.当创建信的对象实例较为复杂时。使用原型模式能够简化对象的创建过程,通过复制一个已有实例能够提高新实例的创建效率
2.原型模式提供了简化的创建结构,工厂方法须要有一个与产品类登记结构同样的工厂等级结构,而原型中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品
3.能够使用深复制的方式保存对象的状态。使用原型模式将对象复制一份并将其状态保存起来,以便在须要的时候使用(如回复到某一历史状态),可辅助实现撤销操作
主要缺点:
1.须要为每个类配备一个克隆方法。并且该克隆方法位于一个类的内部,当对已有的类进行改造时,须要改动源码。违背了“开闭原则”
2.在实现深复制时须要编写较为复杂的代码。并且当对象之间存在多重的嵌套引用时,为了实现深复制。每一层对象相应的类都必须支持深复制,实现起来可能会比較麻烦使用场合:
1.产生对象过程比較复杂,舒适化须要很多资源时。
2.希望框架原型和产生对象分开时;
3.同一个对象可能会供其它调用者同事调用訪问时;