Prototype原型(创建型模式)

依赖关系的倒置

抽象不应该依赖于实现细节,实现细节应该依赖于抽象。

动机:

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需要的变化,这些对象经常面临剧烈的变化,但是他们却拥有比较稳定一致的接口。

如何应对这种变化?如何向“客户程序 (使用这些对象的程序) ”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?

意图:

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

Prototype模式的几个要点:

l         Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。

l         Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象——所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方不断地Clone

l         Prototype模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法或者序列化来实现深拷贝。


StringTokenizer.cs代码示例:

using  System;

namespace  CsharpPats
{
    
//String Tokenizer class
    public class StringTokenizer     {
        
private string data, delimiter;
        
private string[] tokens;
        
private int index;
        
public StringTokenizer(string dataLine)         {
            init(dataLine, 
" ");
                }

        
private void init(String dataLine, string delim) {
            delimiter 
= delim;
            data 
= dataLine;
            tokens 
= data.Split (delimiter.ToCharArray() );
            index 
= 0;
        }

        
public StringTokenizer(string dataLine, string delim) {
           init(dataLine, delim);    
        }

        
public bool hasMoreElements() {
            
return (index < (tokens.Length));
        }

        
public string nextToken() {
            
return nextElement();
        }

        
public string nextElement() {
            
string s = tokens[index++];
            
while((s.Length <=0&& (index<tokens.Length ))
                s 
= tokens[index++];
        
return s;
        }

    }

}

 

csFile.cs代码示例:

using  System;
using  System.IO ;
namespace  CsharpPats
{
    
/// <summary>
    
/// A simple file handlng class
    
/// </summary>

    public class csFile
    
{
        
private string fileName;
        StreamReader ts;
        StreamWriter ws;
        
private bool opened, writeOpened;
        
//-----------
        public csFile() {
            init();
        }

        
//-----------
        private void init() {
            opened 
= false;
            writeOpened 
= false;
        }

        
//-----------
        public csFile(string file_name)     {
            fileName 
= file_name;
            init();
        }

        
//-----------
        public bool OpenForRead(string file_name){
            fileName 
= file_name;
            
try {
                ts 
= new StreamReader (fileName);
                opened
=true;
            }

            
catch(FileNotFoundException ) {
                
return false;
            }

            
return true;
        }

        
//-----------
        public bool OpenForRead() {
            
return OpenForRead(fileName);
        }

        
//-----------
        public string readLine() {
            
return ts.ReadLine ();
        }

        
//-----------
        public void writeLine(string s) {
            ws.WriteLine (s);
        }

        
//-----------
        public void close() {
            
if (opened)
                ts.Close ();
            
if(writeOpened)
                ws.Close();
        }

        
//-----------
        public bool OpenForWrite() {
            
return OpenForWrite(fileName);
        }

        
//-----------
        public bool OpenForWrite(string file_name) {
            
try{
                ws 
= new StreamWriter (file_name);
                fileName 
= file_name;
                writeOpened 
= true;
                
return true;
            }

            
catch(FileNotFoundException ) {
                
return false;
            }

        }

    }

}


Swimmer.cs代码示例:

using  System;
using  CsharpPats;
namespace  SimpleProto
{
    
/// <summary>
    
/// Summary description for Swimmer.
    
/// </summary>

    public class Swimmer:IComparable     {
        
private string name;         //name
        private string lname, frname;//split names
        private int age;            //age
        private string club;        //club initials
        private float time;            //time achieved
        private bool female;        //sex
    
//---------
        public Swimmer(string line) {
            StringTokenizer tok 
= new StringTokenizer(line,",");
            splitName(tok);
            age 
= Convert.ToInt32 (tok.nextToken());
            club 
= tok.nextToken();
            time 
= Convert.ToSingle (tok.nextToken());
            
string sx = tok.nextToken().ToUpper ();
            female 
= sx.Equals ("F");
        }

        
//---------
        private void splitName(StringTokenizer tok) {
            name 
= tok.nextToken();
            
int i = name.IndexOf (" ");
            
if(i >0 ) {
                frname 
= name.Substring (0, i);
                lname 
= name.Substring (i+1).Trim ();
            }

        }

        
//---------
        public int CompareTo(object swo) {
            Swimmer sw 
= (Swimmer)swo;
            
return lname.CompareTo (sw.getLName() );
        }

        
//---------
        public bool isFemale() {
            
return female;
        }

        
//---------
        public int getAge() {
            
return age;
        }

        
//---------
        public float getTime() {
            
return time;
        }

        
//---------
        public string getName() {
            
return name;
        }

        
//---------
        public string getClub() {
            
return club;
        }

        
//---------
        public string getLName() {
            
return lname;
        }

    }

}


SwimData.cs代码示例:

using  System;
using  System.Collections ;
using  CsharpPats;

namespace  SimpleProto
{
    
/// <summary>
    
/// Summary description for SwimData.
    
/// </summary>

    public class SwimData:ICloneable     {
        
protected ArrayList swdata;
        
private int index;
        
//-----
        public SwimData() {
                swdata 
= new ArrayList ();
        }

        
//-----
        public SwimData(ArrayList swd) {
            swdata 
= swd;
            index
=0;
        }

        
//-----
        public int count() {
            
return swdata.Count ;
        }

        
//-----
        public SwimData(string filename)         {
            swdata 
= new ArrayList ();
            csFile fl 
= new csFile(filename);
            fl.OpenForRead ();
            
string s = fl.readLine ();
            
while(s != null{
                Swimmer sw 
= new Swimmer(s);
                swdata.Add (sw);
                s 
= fl.readLine ();
            }

            fl.close ();
        }

        
//-----
        public object Clone() {
            SwimData newsd 
= new SwimData(swdata);
            
return newsd;
        }

        
//-----
        public void moveFirst() {
            index 
= 0;
        }

        
//-----
        public bool hasMoreElements() {
            
return (index < swdata.Count-1 );
        }

        
//-----
        public void sort() {
        
//sort using IComparable interface of Swimmer
            swdata.Sort (0,swdata.Count ,null);
        }

        
//-----
        public Swimmer getSwimmer() {
            
if(index < swdata.Count )
                
return (Swimmer)swdata[index++];
            
else
                
return null;
        }

    }

}


事件代码:

private   void  init()  {
            swdata 
= new SwimData ("swimmers.txt");
            reload();
        }


private   void  reload()  {
            lsKids.Items.Clear ();
            swdata.moveFirst ();
            
while (swdata.hasMoreElements() ) {
                Swimmer sw 
= swdata.getSwimmer ();
                lsKids.Items.Add (sw.getName() );
            }

        
        }


private   void  btClone_Click( object  sender, System.EventArgs e)  {
            SwimData newSd 
= (SwimData)swdata.Clone ();        
            newSd.sort ();
            
while(newSd.hasMoreElements() ) {
                Swimmer sw 
= (Swimmer)newSd.getSwimmer ();
                lsNewKids.Items.Add (sw.getName() );
            }

        }


private   void  btBack_Click( object  sender, System.EventArgs e)  {
            reload();
        }


使用原型模式

SexSwimData.cs代码示例:

using  System;
using  System.Collections ;
namespace  DeepSexClone
{
    
/// <summary>
    
/// Summary description for SexSwimData.
    
/// </summary>

    public class SexSwimData:SwimData
    
{
        
public SexSwimData() {
            
        }

        
public SexSwimData(string filename):base(filename){}
        
public SexSwimData(ArrayList ssd):base(ssd){}
        
public void sort(bool isFemale) {
            ArrayList swd 
= new ArrayList();
            
for (int i = 0; i < swdata.Count ; i++{
                Swimmer sw 
=(Swimmer)swdata[i];
                
if (isFemale == sw.isFemale() ) {
                    swd.Add (sw);
                }

            }

            swdata 
= swd;
        }

        
    }

}


Swimmer.cs代码示例:

using  System;
using  CsharpPats;
namespace  DeepSexClone
{
    
/// <summary>
    
/// Summary description for Swimmer.
    
/// </summary>

    public class Swimmer:IComparable     {
        
private string name;         //name
        private string lname, frname;//split names
        private int age;            //age
        private string club;        //club initials
        private float time;            //time achieved
        private bool female;        //sex
    
//---------
        public Swimmer(string line) {
            StringTokenizer tok 
= new StringTokenizer(line,",");
            splitName(tok);
            age 
= Convert.ToInt32 (tok.nextToken());
            club 
= tok.nextToken();
            time 
= Convert.ToSingle (tok.nextToken());
            
string sx = tok.nextToken().ToUpper ().Trim ();
            female 
= sx.Equals ("F");
        }

        
//---------
        private void splitName(StringTokenizer tok) {
            name 
= tok.nextToken();
            
int i = name.IndexOf (" ");
            
if (i > 0 ) {
                frname 
= name.Substring (0, i);
                lname 
= name.Substring (i + 1).Trim ();
            }

        }

        
//---------
        public int CompareTo(object swo) {
            Swimmer sw 
= (Swimmer)swo;
            
return lname.CompareTo (sw.getLName() );
        }

        
//---------
        public bool isFemale() {
            
return female;
        }

        
//---------
        public int getAge() {
            
return age;
        }

        
//---------
        public float getTime() {
            
return time;
        }

        
//---------
        public string getName() {
            
return name;
        }

        
//---------
        public string getClub() {
            
return club;
        }

        
//---------
        public string getLName() {
            
return lname;
        }

    }

}


SwimData.cs代码示例:

using  System;
using  System.Collections ;
using  CsharpPats;

namespace  DeepSexClone
{
    
/// <summary>
    
/// Summary description for SwimData.
    
/// </summary>

    public class SwimData    {
        
protected ArrayList swdata;
        
private int index;
        
//-----
        public SwimData() {
                swdata 
= new ArrayList ();
        }

        
//-----
        public SwimData(ArrayList swd) {
            swdata 
= swd;
            index
=0;
        }

        
//-----
        public void cloneMe(SwimData swdat) {
            swdata 
= new ArrayList ();
            ArrayList swd
=swdat.getData ();
            
//copy in swimmer objects
            for(int i=0; i < swd.Count ; i++
                swdata.Add (swd[i]);
        
        }

        
//-----
        public int count() {
            
return swdata.Count ;
        }

        
//-----
        public SwimData(string filename)         {
            swdata 
= new ArrayList ();
            csFile fl 
= new csFile(filename);
            fl.OpenForRead ();
            
string s = fl.readLine ();
            
while(s != null{
                Swimmer sw 
= new Swimmer(s);
                swdata.Add (sw);
                s 
= fl.readLine ();
            }

            fl.close ();
        }

        
//-----
        public ArrayList getData() {
            
return swdata;
        }

        
//-----
        public void moveFirst() {
            index 
= 0;
        }

        
//-----
        public bool hasMoreElements() {
            
return (index < swdata.Count-1 );
        }

        
//-----
        public void sort() {
        
//sort using IComparable interface of Swimmer
            swdata.Sort (0, swdata.Count , null);
        }

        
//-----
        public Swimmer getSwimmer() {
            
if(index < swdata.Count )
                
return (Swimmer)swdata[index++];
            
else
                
return null;
        }

    }

}


事件代码:

private   void  init()  {
            swdata 
= new SexSwimData ("swimmers.txt");
            reload();
        }


private   void  reload()  {
            lsKids.Items.Clear ();
            swdata.moveFirst ();
            
while (swdata.hasMoreElements() ) {
                Swimmer sw 
= swdata.getSwimmer ();
                lsKids.Items.Add (sw.getName() );
            }

        

private   void  btClone_Click( object  sender, System.EventArgs e)  {
            SexSwimData newSd 
= new SexSwimData ();        
            newSd.cloneMe (swdata);
            newSd.sort (opFemale.Checked );
            lsNewKids.Items.Clear() ;
            
while(newSd.hasMoreElements() ) {
                Swimmer sw 
= (Swimmer)newSd.getSwimmer ();
                lsNewKids.Items.Add (sw.getName() );
            }

        }


private   void  btBack_Click( object  sender, System.EventArgs e)  {
            reload();
        }


具有相同接口的不同类

AgeSwimData.cs代码示例:

using  System;
using  System.Collections ;
namespace  DeepSexClone
{
    
/// <summary>
    
/// Summary description for SexSwimData.
    
/// </summary>

    public class AgeSwimData:SwimData
    
{
        ArrayList swd;
        
public AgeSwimData() {
            swdata 
= new ArrayList ();
        }

        
//------
        public AgeSwimData(string filename):base(filename){}
        
public AgeSwimData(ArrayList ssd):base(ssd){}
        
//------
        public override void cloneMe(SwimData swdat) {
            swd 
= swdat.getData ();
        }

        
//------
        public override void sort() {
            Swimmer[] sws 
= new Swimmer[swd.Count ];
            
//copy in swimmer objects
            for(int i=0; i < swd.Count ; i++{
                sws[i] 
= (Swimmer)swd[i];
            }

            
//sort into increasing order
            forint i=0; i< sws.Length ; i++{
                
for (int j = i; j< sws.Length ; j++{
                    
if (sws[i].getAge ()>sws[j].getAge ()) {
                        Swimmer sw 
= sws[i];
                        sws[i]
=sws[j];
                        sws[j]
=sw;
                    }

                }

            }

            
int age = sws[0].getAge ();
            
int agecount = 0;
             
int k = 0;
            swdata 
= new ArrayList ();
            
bool quit = false;
            
            
while( k < sws.Length && ! quit ) {
                
while(sws[k].getAge() ==age && ! quit) {
                    agecount
++;
                    
if(k < sws.Length -1)
                        k
++;
                    
else
                        quit
= true;
                }

                
//create a new Swimmer with a series of X's for a name
                
//for each new age
                string name = "";
                
for(int j = 0; j < agecount; j++)
                    name 
+="X";
                Swimmer sw 
= new Swimmer(age.ToString() + " " +
                    name 
+ "," + age.ToString() + ",club,0,F");
                swdata.Add (sw);
                agecount 
= 0;
                
if(quit)
                    age 
= 0;
                
else
                    age 
= sws[k].getAge ();
            }

        
        }

    }

}


用原型模式能根据需要克隆类,这样,在运行时就可以添加或删除类。根据程序运行情况,可以在运行时更改一个类的内部数据表示,也可以在运行时指定新对象而无需创建一个新类。

C#实施原型模式的困难在于:如果类早已存在,则不能改变它们来增加需要的克隆方法。另外,间接引用其他类的列也不能被真正克隆。

拷贝原型类的想法意味着,你对类中的数据或方法有足够的访问权,这样在克隆之后可以修改它们。这可能需要向原型类中添加数据访问方法,这样在克隆了该类后,就能修改数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值