【原型模式】:
用原型執行個體指定建立對象的種類,并且通過拷貝這些原型建立新的對象。
适用性
當要執行個體化的類是在運作時刻指定時,例如,通過動态裝載;
或者為了避免建立一個與産品類層次平行的工廠類層次時;
或者當一個類的執行個體隻能有幾個不同狀态組合中的一種時。
建立相應數目的原型并克隆它們可能比每次用合适的狀态手工執行個體化該類更友善一些。
【實作代碼】
using system;
using system.collections.generic;
using system.linq;
using system.text;
namespace consoleapplication1
{
//原型模式:其實就是從一個對象再建立另一個可制定的對象,而且不需知道任何建立的細節。
//原型類;
abstract class prototype
{
private string id;
public prototype(string id)
{
this.id = id;
}
public string id
get { return id; }
public abstract prototype copy();//抽象類關鍵就是有這樣一個clone方法;
}
//具體原型類;
class concreteptototypel : prototype
public concreteptototypel(string id)
: base(id)
{ }
public override prototype copy()
return (prototype)this.memberwiseclone();
/*memberwiseclone 方法建立一個淺表副本,方法是建立一個新對象,
然後将目前對象的非靜态字段複制到該新對象。
如果字段是值類型的,則對該字段執行逐位複制。
如果字段是引用類型,則複制引用但不複制引用的對象;
是以,原始對象及其複本引用同一對象。*/
}
//客戶代碼
class program
static void main(string[] args)
concreteptototypel p1 = new concreteptototypel("i");
//克隆類concreteptototypel的對象p1就能得到新執行個體c1;
concreteptototypel c1 = (concreteptototypel)p1.copy();
console.writeline("cloned:{0}",c1.id);
console.read();
【執行個體代碼2.】
//由于.net在system命名空間中提供了iconeable接口,
//其中唯一的一個方法就是clone。這樣就隻需實作這個接口就可以完成原型模式了。
//履歷類;
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.age = age;
this.sex = sex;
//設定工作經曆;
public void setworkperience(string timearea, string company)
this.company = company;
this.timearea = timearea;
//顯示;
public void display()
console.writeline("{0}{1}{2}",name ,sex,age);
console.writeline("工作經曆:{0} {1}",timearea,company);
public object clone()
return (object)this.memberwiseclone();
//客戶代碼
class program
static void main(string[] args)
{
resume a = new resume("小山");
a.setpersonalinfo("男","22");
a.setworkperience("2006-2007","大一年級");
resume b = (resume)a.clone();
b.setpersonalinfo("張小山","22");
b.setworkperience("2007-2008","大二年級");
resume c = (resume)a.clone();
c.setpersonalinfo("張 山","22");
c.setworkperience("2008-2009","大三年級");
a.display();
b.display();
c.display();
console.read();
}
【淺表複制】
memberwiseclone 方法建立一個淺表副本,方法是建立一個新對象,然後将目前對象的非靜态字段複制到該新對象。如果字段是值類型的,則對該字段執行逐位複制。如果字段是引用類型,則複制引用但不複制引用的對象;是以,原始對象及其複本引用同一對象。使用實作 icloneable 接口的類執行對象的淺表或深層複制。
【實作代碼】:
private workexperience work;//引用“工作經曆”對象;
//在“履歷”類執行個體化的同時,執行個體化”工作經曆“;
work=new workexperience();
public void setworkperience(string workdate, string company)
work.workdate=workdate;
work.company=company;
console.writeline("工作經曆:{0} {1}",
work.workdate,work.company);
//工作經曆類;
class workexperience
{
private string workdate;
public string workdate
{
get{return workdate;}
set{workdate=value;}
}
private string company;
public string company
get{return company;}
set{company=value;}
}
}
c.setpersonalinfo("張山","22");
/這裡b和c都克隆于a,但當它們都設定了工作經曆時,我們希望的結果是現實三個不同的結果;但是,結果它們卻是一樣的,都顯示最後的設定。因為隻是複制了引用,沒有真正複制對象!
【深表複制】
//工作經曆類;
class workexperience:icloneable // ①讓“工作經曆”類實作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();
work=new workexperience();
private resume(workexperience work)
// ③提供clone方法調用私有的構造函數,以便克隆“工作經曆”的資料;
this.work = (workexperience)work.clone();
console.writeline("工作經曆:{0}
{1}",work.workdate,work.company);
// ④調用私有的構造方法,完成克隆"工作經曆"類的資料;
resume obj = new resume(this.work);
obj.name = this.name;
obj.sex = this.sex;
obj.age = this.age;
return obj;