介绍 :
原型模式(Prototype)创建型模式。用原型表示实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式其实就是从一个再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
在原型模式结构图中包含如下几个角色:
1、Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。
2、 ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
3、 Client(客户类):让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。由于客户类针对抽象原型类Prototype编程,因此用户可以根据需要选择具体原型类,系统具有较好的可扩展性,增加或更换具体原型类都很方便。
优点:
1、运行时刻增加和删除产品2、改变值以指定新对象
3、改变结构以指定新对象
4、减少子类的构造
5、用类动态配置应用
缺点:
Prototype模式最主要的缺点就是每个类必须配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但是已有的类进行改造时不一定是件容易的事。
举例
我们在找工作的时候需要准备一些简历,看到自己中意的公司就会投一份简历,那么如何让程序能够执行出这份简历呢?
客户端代码
static void Main(string[] args)
{
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWorkExperience("1998-2000", "xx公司");
Resume b = new Resume("大鸟");
b.SetPersonalInfo("男", "29");
b.SetWorkExperience("1998-2000", "xx公司");
Resume c = new Resume("大鸟");
c.SetPersonalInfo("男", "29");
c.SetWorkExperience("1998-2000", "xx公司");
a.Display();
b.Display();
c.Display();
Console.Read();
}
简历类
//简历类
class Resume
{
private string name;
private string sex;
private string age;
private string timeArea;
private string company;
public Resume(string name)
{
this.name = name;
}
//设置个人信息
public void SetPersonalInfo(string sex, string age)
{
this.sex = sex;
this.age = age;
}
//设置工作经历
public void SetWorkExperience(string timeArea, string company)
{
this.timeArea = timeArea;
this.company = company;
}
//显示
public void Display()
{
Console.WriteLine("{0} {1} {2}",name,sex,age);
Console.WriteLine("工作经验: {0} {1}",timeArea ,company);
}
}
效果
如果我的简历修改修改怎么办?
虽然程序能够运行,也能够得到我们想要的结果,但是大家有没有发现在客户端调用代码的时候这三份简历需要三次实例化,如果简历上的年龄或者工作经验需要改动,那么就需要三次的改动, 如果我有一百份简历,难道需要一个一个的需改么?那还不如重新再重新再写一遍呢。
接下来就是使用传引用的方法来解决
客户端代码(其他代码相同)
static void Main(string[] args)
{
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "28");
a.SetWorkExperience("1998-2000", "xx公司");
Resume b = a;
Resume c = a;
a.Display();
b.Display();
c.Display();
Console.Read();
}
哈,这样我们只需要改动第一份简历,剩下的简历也都自动的改动了。
传引用的方法就是把a的拿来“用”。但是并没有实际的内容。因为都是第一份的东西,如果我需要在第一份上的简历年龄写29岁,第二份简历上的年龄写28岁,那该怎么办呢?
下面就介绍克隆的方法
效果图
客户端代码
static void Main(string[] args)
{
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "28");
a.SetWorkExperience("1998-2000", "XX公司");
//只需要调用Clone方法就可以实现新简历的生成,并且就可以在修改新简历的细节
Resume b = (Resume)a.Clone();
b.SetWorkExperience("1998-2006", "YY企业");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
a.Display();
b.Display();
c.Display();
Console.Read();
}
简历类
class Resume : ICloneable
{
private string name;
private string sex;
private string age;
private string timeArea;
private string company;
public Resume(string name)
{
this.name = name;
}
//设置个人信息
public void SetPersonalInfo(string sex, string age)
{
this.sex = sex;
this.age = age;
}
//设置工作经历
public void SetWorkExperience(string timeArea, string company)
{
this.timeArea = timeArea;
this.company = company;
}
//显示
public void Display()
{
Console.WriteLine("{0} {1} {2}", name, sex, age);
Console.WriteLine("工作经历:{0} {1}", timeArea, company);
//实现接口的方法,用来克隆对象
}
public Object Clone()
{
return (Object)this.MemberwiseClone();//逐一克隆
}
}