目录
一、原型模式
通过给出一个原型对象来指明所要创建的对象类型。然后复制这个原型对象来创建更多的同类型对象。
用原型实例创建对象的种类,并且通过拷贝这些原型创建新的对象。
应用场景:
1、需要从一个对象出发,得到若干个和其他状态相同,并可以相互独立变化状态的对象。
2、对象创建和对象构建独立。
PROS AND CONS
PROS
1、允许动态增加或减少产品类,创建产品类对象实例的方法是产品类内部具有的,增加新的产品对结构没有影响。
2、提供了简化的创建结构。
CONS
1、每个原型的子类必须实现Clone接口。
2、包含引用类型对象时要实现深复制,比较麻烦。
二、原型模式角色
1、客户角色:提出创建对象请求
2、抽象原型:抽象类,给出具体原型所需要的接口。在C#中,抽象原型通常实现ICloneable接口。
3、具体原型:被复制的对象,实现抽象类接口。
三、代码实例一
原型模式类似于c++中的深浅拷贝,通过一个原型对象来复制出其他的同类型对象。
利用c#中的ICloneable接口,我们可以实现浅复制,但当数据比较复杂,例如有引用类型,这事要利用深复制来完成功能。
例如一个简历类代码实例:
第一个类是工作经验类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 原型模式一
{
class WorkExperience : ICloneable
{
private string workDate;
private string workCompany;
public WorkExperience(string workDate, string workCompany)
{
this.workDate = workDate;
this.workCompany = workCompany;
}
public string WorkDate
{
get { return workDate; }
set { workDate=value; }
}
public string WorkCompany
{
get { return workCompany; }
set { workCompany = value; }
}
public object Clone()
{
return (Object)(this.MemberwiseClone());
}
}
}
第二个类是简历类,里面包含工作经验类对象,并完成深复制功能。
要仔细体会一下这里的写法,感觉很巧妙。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 原型模式一
{
class Resume : ICloneable
{
private string name;
private string age;
private string major;
private WorkExperience work;
public Resume(string name)
{
this.name = name;
}
private Resume(WorkExperience work)
{
this.work = (WorkExperience)work.Clone();
}
public void SetPersonalInfor(string age,string major)
{
this.age = age;
this.major = major;
}
public void SetWorkExperience(WorkExperience work)
{
this.work = work;
}
public void show()
{
Console.WriteLine("{0},{1},{2}", name, age, major);
Console.WriteLine("工作经历:{0},{1}", work.WorkDate, work.WorkCompany);
}
public object Clone()
{
Resume obj = new Resume(this.work );
obj.name = this.name;
obj.age = this.age;
obj.major = this.major;
return obj;
}
}
}
接着是测试类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 原型模式一
{
class Program
{
static void Main(string[] args)
{
Resume Pa = new Resume("小李");
Pa.SetPersonalInfor("19", "计算机");
Pa.SetWorkExperience(new WorkExperience ("1999-2002", "百度"));
Resume Pb = (Resume)Pa.Clone();
Pb.SetPersonalInfor("18", "数学");
Pb.SetWorkExperience(new WorkExperience("2001-2007", "腾讯"));
Pa.show();
Pb.show();
}
}
}
四、代码实例二
抽象原型类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeOne
{
abstract class Prototype
{
private string id;
protected Prototype(string id)
{
this.Id = id;
}
public string Id { get => id; set => id = value; }
abstract public Prototype Clone();
}
}
具体原型类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeOne
{
class ConcretePrototypeOne : Prototype
{
public ConcretePrototypeOne(string id) : base(id) { }
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeOne
{
class ConcretePrototypeTwo : Prototype
{
public ConcretePrototypeTwo(string id):base(id){}
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();
}
}
}
测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PrototypeOne
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
ConcretePrototypeOne c1 = new ConcretePrototypeOne("99");
ConcretePrototypeOne c11 = (ConcretePrototypeOne)c1.Clone();
Console.WriteLine("::{0}", c11.Id);
}
}
}
五、代码实例三
订单处理系统 现在有一个订单处理系统,里面有一个保存订单的业务功能,需求:每当订单的预定产品数量超过1000的时候,就需要把订单拆成两份订单来保存。如果拆成两份后还是超过1000,则继续拆分,直到每份产品预订数量不超过1000. 根据业务,目前的订单系统分成两种,一种是个人订单、一种是公司订单。 客户名称、产品对象(ID,Name),订购产品数量。 公司名称、产品对象(ID,Name),订购产品数量
订单接口:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeTwo
{
abstract class Order:ICloneable
{
abstract public void SetInformation(string name,int num);
abstract public void SetProductInformation(string name, int id);
abstract public void Show();
abstract public Object Clone();
abstract public int GetNum();
abstract public string GetName();
}
}
订单类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeTwo
{
class CompanyOrder : Order
{
private string name;
private int num;
private Product product;
public CompanyOrder(string name, int num)
{
product = new Product();//注意初始化
this.name = name;
this.num = num;
}
private CompanyOrder(Product p)
{
this.product = (Product)p.Clone();//
}
public override object Clone()
{
CompanyOrder com = new CompanyOrder(this.product);//
com.name = name;
com.num = num;
return com;
}
public override string GetName()
{
return name;
}
public override int GetNum()
{
return num;
}
public override void SetInformation(string name, int num)
{
this.name = name;
this.num = num;
}
public override void SetProductInformation(string name, int id)
{
this.product.Name = name;
this.product.Id = id;
}
public override void Show()
{
Console.WriteLine("所属者:{0} 数量:{1}", name, num);
}
}
}
产品类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeTwo
{
class Product
{
private int id;
private string name;
public Product()
{
}
public Product(string name, int id)
{
this.Id = id;
this.Name = name;
}
public int Id { get => id; set => id = value; }
public string Name { get => name; set => name = value; }
public Object Clone()
{
return (Object)this.MemberwiseClone();
}
}
}
订单处理类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrototypeTwo
{
class OrderMan
{
private Order order;
private List<Order> list = new List<Order>();
public OrderMan(Order order)
{
this.order = order;
}
public void Process()
{
int len = order.GetNum();
while(len>1000)
{
len -= 1000;
CompanyOrder c11 = (CompanyOrder)order.Clone();
c11.SetInformation(order.GetName(), 1000);
list.Add(c11);
}
order.SetInformation(order.GetName(), len);
list.Add(order);
}
public void Show()
{
foreach(Order o1 in list)
{
o1.Show();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PrototypeTwo
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
CompanyOrder c1 = new CompanyOrder("阿里",7503);
c1.SetProductInformation("A", 1);//不要忘了
int num = c1.GetNum();
OrderMan o = new OrderMan(c1);
o.Process();
o.Show();
//while(num>1000)
//{
// CompanyOrder c11 = (CompanyOrder)c1.Clone();
// c11.SetInformation(c1.GetName(), 1000);
// num -= 1000;
// c11.Show();
//}
//Console.WriteLine("------");
//c1.SetInformation(c1.GetName(), num);
//c1.Show();
//k --c+u
}
}
}