C#设计模式之:原型模式

原型模式(Prototype)

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。

UML
这里写图片描述

代码

abstract class Prototype
{
    private string id;

    public Prototype(string id)
    {
        this.Id = id;
    }

    public string Id { get => id; set => id = value; }

    public abstract Prototype Clone();
}
class ConcretePrototype1 : Prototype
{
    public ConcretePrototype1(string id) : base(id)
    {

    }

    public override Prototype Clone()
    {
        return (Prototype)this.MemberwiseClone();//浅拷贝
    }
}
// test
ConcretePrototype1 p1 = new ConcretePrototype1("I");
ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
Console.WriteLine("Cloned: {0}", c1.Id);
// result
Cloned: I

从用户层次来看,不用实例化ConcreteProtype1,直接克隆就行了

一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这即隐藏了对象创建的细节,又对性能是大大的提高。它等于不用重新初始化对象,而是动态地获得对象运行时的状态。

.NetSystem命名空间中提供了ICloneable接口,其中有一个唯一的方法Clone( ),你只要实现这个接口就可以完成原型模式

MemberwiseClone( ) 方法:如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象,因此原始对象及其复本引用同一对象。

使用浅拷贝的样例

class WorkExperience
{
    private string workDate;
    private string company;

    public string WorkDate { get => workDate; set => workDate = value; }
    public string Company { get => company; set => company = value; }
}
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();
    }

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

    public void SetWordExperience(string timeDate, string company)
    {
        work.WorkDate = timeDate;
        work.Company = company;
    }

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

    public object Clone()
    {
        return (Object)this.MemberwiseClone();
    }
}
// test
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWordExperience("2001-2008", "XX 公司");

Resume b = (Resume)a.Clone();
b.SetWordExperience("1998-2006", "YY 公司");

Resume c = (Resume)a.Clone();
c.SetWordExperience("1998-2018", "ZZ 公司");

a.Display();
b.Display();
c.Display();
// result
大鸟 男 29
工作经历:1998-2018 ZZ 公司
大鸟 男 29
工作经历:1998-2018 ZZ 公司
大鸟 男 29
工作经历:1998-2018 ZZ 公司

浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其它对象的引用都仍然指向原来的对象
深拷贝:把引用对象的变量指向复制过来的新对象,而不是原来的被引用的对象

深拷贝实现

class WorkExperience : ICloneable
{
    private string workDate;
    private string company;

    public string WorkDate { get => workDate; set => workDate = value; }
    public string Company { get => company; set => company = value; }

    public object Clone()
    {
        return (Object)this.MemberwiseClone();
    }
}
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 SetWordExperience(string timeDate, string company)
    {
        work.WorkDate = timeDate;
        work.Company = company;
    }

    public void Display()
    {
        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;
    }
}
// test 上同
// result
大鸟 男 29
工作经历:2001-2008 XX 公司
大鸟 男 29
工作经历:1998-2006 YY 公司
大鸟 男 29
工作经历:1998-2018 ZZ 公司
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值