关闭

C# 设计模式之原型模式(Prototype)

标签: c#prototype设计模式
168人阅读 评论(0) 收藏 举报

1.简历复印

先用一个基本的简历类如下(注:本文示例均引用于《大话设计模式》)

using System;
using System.Collections.Generic;
using System.Text;

namespace Resume
{
    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 Diaplay()
        {
            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("男", "29");
            a.SetWorkExperience("1998-2000", "XX公司");
            Resume b = a;
            Resume c = a;

            a.Diaplay();
            b.Diaplay();
            c.Diaplay();

            Console.Read();
        }

不过,此种方法传的是引用,而不是值,a,b,c其实还是同一份简历。


2.原型模式

我们可以用原型模式(Prototype),所謂原型模式,是指从一个对象创建另外一个可定制的对象,而且我们不需要知道任何创建的细节.

.NET在System命名空间中提供了ICloneable接口,这个接口中只有唯一一个方法Clone().我们只需要实现ICloneable这个接口即可实现原型模式.

WorkExperience类是"工作经历"原型类代码如下:

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();
      }
    }



在简历类中用"this.work = (WorkExperience)work.Clone();"语句即可实现原型类的克隆.


3.浅复制和深复制:

       1) 浅复制

MemberwiseClone()方法引用的字段如果是值类型的,则对该字段进行逐位复制;如果字段是引用类型,则复制引用但不复制引用的对象.

即原始对象及其复本引用同一对象.

当不同的复本的引用值改变时,原始对象及所有复本的引用值都会改变.这就是浅复制.

2) 深复制

当我们希望不同的复本的引用值有所区别时,就要使用深复制.

深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象.

如示例中复制简历时,工作经历就相当于一个引用对象.可以对简历类的Clone()方法做些改变.

如下所示,调用简历类中私有的构造方法,克隆工作经历,这样就实现了深复制.

 public object Clone()
        {
            Resume obj = new Resume(this.work);
            obj.name = this.name;
            obj.sex = this.sex;
            obj.age = this.age;
            return obj;
        }

完整代码如下所示:

using System;
using System.Collections.Generic;
using System.Text;

namespace Resume
{
    public class Resume: ICloneable
    {
        private string name;
        private string sex;
        private string age;

        private WorkExperience work;

        public Resume(string name)
        {
            this.name=name;
            work = new WorkExperience();
        }

        private Resume(WorkExperience work)
        {
            this.work = (WorkExperience)work.Clone();
        }

        public void SetPersonalInfo(string sex, string age)
        {
            this.sex = sex;
            this.age = age;
        }

        public void SetWorkExperience(string workDate, string company)
        {
            work.WorkDate = workDate;
            work.Company = company;
        }

        public void Diaplay()
        {
            Console.WriteLine("{0} {1} {2}", name, sex, age);
            Console.WriteLine("工作經歷: {0} {1}", work.WorkDate, work.Company);
        }

        public object Clone()
        {
            Resume obj = new Resume(this.work);
            obj.name = this.name;
            obj.sex = this.sex;
            obj.age = this.age;
            return obj;
        }

        static void Main(string[] args)
        {
            Resume a = new Resume("大鳥");
            a.SetPersonalInfo("男", "29");
            a.SetWorkExperience("1998-2000", "XX公司");

            Resume b = (Resume)a.Clone();
            b.SetWorkExperience("1998-2006", "YY企業");

            Resume c = (Resume)a.Clone();
            c.SetPersonalInfo("男", "24");
            c.SetWorkExperience("1998-2006", "ZZ企業");

            a.Diaplay();
            b.Diaplay();
            c.Diaplay();

            Console.Read();
        }
    }
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:170次
    • 积分:11
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档