设计模式学习笔记-原型模式

概述:                                                                                                       

原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

实用场合:                                                                                                 

1.当一个系统应该独立于它的产品创建、构成和表示时。

2、当要实例化的类是在运行时刻指定时,例如通过动态装载。

3、为了避免创建一个与产品类层次平行的工厂类层次时。

4、当一个类的实例只能有几个不同状态组合中的一种时。

类图:                                                                                                      

1.定义一个抽象类,声明克隆自身的接口

    /// <summary>
/// 抽象原型类,声明一个克隆自身的接口
/// </summary>
abstract class Prototype
{
private string id;
public Prototype(string id)
{
this.id = id;
}
public string Id { get { return id; } }
/// <summary>
/// 关键的克隆接口
/// </summary>
/// <returns></returns>
public abstract Prototype Clone();
}

2.具体的原型类,实现接口

    /// <summary>
/// 具体原型类,实现一个克隆自身的操作
/// </summary>
class ConcretePrototype : Prototype
{
/// <summary>
/// 调用基类的构造函数
/// </summary>
/// <param name="id"></param>
public ConcretePrototype(string id) : base(id) { }

public override Prototype Clone()
{
//创建当前对象的浅表副本,方法是创建一个新的对象,然后将当前对象的非静态字段复制到该对象
//如果字段是值类型,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象
//因此,原始对象及其副本引用同一对象。
return (Prototype)this.MemberwiseClone();
}
}

  3.客户端调用

        /// <summary>
/// 测试原型方法
/// </summary>
static void TestPrototype()
{
ConcretePrototype p1
= new ConcretePrototype1("I");
//克隆p1就能得到新的实例c1
ConcretePrototype c1 = (ConcretePrototype)p1.Clone();

Console.WriteLine(
"Cloned:{0}",c1.Id);

Console.Read();
}

补充:                                                                                                       

实际上.net framework已经提供了ICloneable接口,只要实现这个接口就可以完成原型了,上面的原始代码只实现了浅表复制,对于深复制看下面两个例子的不同之处就可以了。

举例说明:                                                                                                 

这里用大话设计模式里的例子

浅表复制

View Code
 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;
}
/// <summary>
/// 设置个人信息
/// </summary>
/// <param name="sex"></param>
/// <param name="age"></param>
public void SetPersonalInfo(string sex,string age)
{
this.age = age;
this.sex = sex;
}
public void SetWorkExperience(string timeArea,string company)
{
this.timeArea = timeArea;
this.company = company;
}
public void Display()
{
Console.WriteLine(
"{0} {1} {2}",name,age,sex);
Console.WriteLine(
"工作经历:{0} {1}",timeArea,company);
}
public Object Clone()
{
return (Object)this.MemberwiseClone();
}
}
//客户端调用
/// <summary>
/// 测试简原型历类
/// </summary>
static void TestPrototypeResume()
{
Resume a
= new Resume("小鸟");
a.SetPersonalInfo(
"","25");
a.SetWorkExperience(
"2007-2008","xx科技");

Resume b
= (Resume)a.Clone();
b.SetWorkExperience(
"2008-2009","xxx文化");

Resume c
= (Resume)a.Clone();
c.SetPersonalInfo(
"","26");

a.Display();
b.Display();
c.Display();
Console.Read();

}

深复制:就是将引用类型里的值也一并复制了,二不仅仅是复制引用类型对象本身,客户端调用同浅表复制

View Code
    /// <summary>
/// 深表制
/// </summary>
class WorkExperience : ICloneable
{


private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}
private string company;
public string Company
{
get { return company; }
set { company = value; }
}
public Object Clone()
{
return (Object)this.MemberwiseClone();
}
}
class Resume2 : ICloneable
{
private string name;
private string sex;
private string age;
private WorkExperience work;
public Resume2(string name)
{
this.name = name;
work
= new WorkExperience();
}
/// <summary>
/// 提供Clone方法调用的私有构造函数,克隆工作经历的数据
/// </summary>
/// <param name="work"></param>
private Resume2(WorkExperience work)
{
this.work = (WorkExperience)work.Clone();
}

/// <summary>
/// 设置个人信息
/// </summary>
/// <param name="sex"></param>
/// <param name="age"></param>
public void SetPersonalInfo(string sex, string age)
{
this.age = age;
this.sex = sex;
}
//设置工作经历
public void SetWorkExperience(string workDate, string company)
{
work.WorkDate
= workDate;
work.Company
= company;
}
public void Display()
{
Console.WriteLine(
"{0} {1} {2}", name, age, sex);
Console.WriteLine(
"工作经历:{0} {1}", work.WorkDate, work.Company);
}
public Object Clone()
{
//关键部分:调用私有的构造方法,让工作经历克隆完成,然后给这个简历的相关字段赋值,最终返回一个深复制的对象
Resume2 obj = new Resume2(this.work);
obj.name
= this.name;
obj.sex
= this.sex;
obj.age
= this.age;
return obj;

}
}

小结:                                                                                                        

原型模式有意思吧

posted @ 2011-08-19 10:52  叶鹏  阅读(846)  评论(0编辑  收藏  举报