• 设计模式学习笔记原型模式


    概述:                                                                                                       

    原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

    实用场合:                                                                                                 

    1.当一个系统应该独立于它的产品创建、构成和表示时。

    2、当要实例化的类是在运行时刻指定时,例如通过动态装载。

    3、为了避免创建一个与产品类层次平行的工厂类层次时。

    4、当一个类的实例只能有几个不同状态组合中的一种时。

    类图:                                                                                                      

    1.定义一个抽象类,声明克隆自身的接口

        /// <summary>
    /// 抽象原型类,声明一个克隆自身的接口
    /// </summary>
    abstract class Prototype
    {
    private string id;
    public Prototype(string id)
    {
    this.id = id;
    }
    public string Id { get { return id; } }
    /// <summary>
    /// 关键的克隆接口
    /// </summary>
    /// <returns></returns>
    public abstract Prototype Clone();
    }

    2.具体的原型类,实现接口

        /// <summary>
    /// 具体原型类,实现一个克隆自身的操作
    /// </summary>
    class ConcretePrototype : Prototype
    {
    /// <summary>
    /// 调用基类的构造函数
    /// </summary>
    /// <param name="id"></param>
    public ConcretePrototype(string id) : base(id) { }

    public override Prototype Clone()
    {
    //创建当前对象的浅表副本,方法是创建一个新的对象,然后将当前对象的非静态字段复制到该对象
    //如果字段是值类型,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象
    //因此,原始对象及其副本引用同一对象。
    return (Prototype)this.MemberwiseClone();
    }
    }

      3.客户端调用

            /// <summary>
    /// 测试原型方法
    /// </summary>
    static void TestPrototype()
    {
    ConcretePrototype p1
    = new ConcretePrototype1("I");
    //克隆p1就能得到新的实例c1
    ConcretePrototype c1 = (ConcretePrototype)p1.Clone();

    Console.WriteLine(
    "Cloned:{0}",c1.Id);

    Console.Read();
    }

    补充:                                                                                                       

    实际上.net framework已经提供了ICloneable接口,只要实现这个接口就可以完成原型了,上面的原始代码只实现了浅表复制,对于深复制看下面两个例子的不同之处就可以了。

    举例说明:                                                                                                 

    这里用大话设计模式里的例子

    浅表复制

    View Code
     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;
    }
    /// <summary>
    /// 设置个人信息
    /// </summary>
    /// <param name="sex"></param>
    /// <param name="age"></param>
    public void SetPersonalInfo(string sex,string age)
    {
    this.age = age;
    this.sex = sex;
    }
    public void SetWorkExperience(string timeArea,string company)
    {
    this.timeArea = timeArea;
    this.company = company;
    }
    public void Display()
    {
    Console.WriteLine(
    "{0} {1} {2}",name,age,sex);
    Console.WriteLine(
    "工作经历:{0} {1}",timeArea,company);
    }
    public Object Clone()
    {
    return (Object)this.MemberwiseClone();
    }
    }
    //客户端调用
    /// <summary>
    /// 测试简原型历类
    /// </summary>
    static void TestPrototypeResume()
    {
    Resume a
    = new Resume("小鸟");
    a.SetPersonalInfo(
    "","25");
    a.SetWorkExperience(
    "2007-2008","xx科技");

    Resume b
    = (Resume)a.Clone();
    b.SetWorkExperience(
    "2008-2009","xxx文化");

    Resume c
    = (Resume)a.Clone();
    c.SetPersonalInfo(
    "","26");

    a.Display();
    b.Display();
    c.Display();
    Console.Read();

    }

    深复制:就是将引用类型里的值也一并复制了,二不仅仅是复制引用类型对象本身,客户端调用同浅表复制

    View Code
        /// <summary>
    /// 深表制
    /// </summary>
    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();
    }
    }
    class Resume2 : ICloneable
    {
    private string name;
    private string sex;
    private string age;
    private WorkExperience work;
    public Resume2(string name)
    {
    this.name = name;
    work
    = new WorkExperience();
    }
    /// <summary>
    /// 提供Clone方法调用的私有构造函数,克隆工作经历的数据
    /// </summary>
    /// <param name="work"></param>
    private Resume2(WorkExperience work)
    {
    this.work = (WorkExperience)work.Clone();
    }

    /// <summary>
    /// 设置个人信息
    /// </summary>
    /// <param name="sex"></param>
    /// <param name="age"></param>
    public void SetPersonalInfo(string sex, string age)
    {
    this.age = age;
    this.sex = sex;
    }
    //设置工作经历
    public void SetWorkExperience(string workDate, string company)
    {
    work.WorkDate
    = workDate;
    work.Company
    = company;
    }
    public void Display()
    {
    Console.WriteLine(
    "{0} {1} {2}", name, age, sex);
    Console.WriteLine(
    "工作经历:{0} {1}", work.WorkDate, work.Company);
    }
    public Object Clone()
    {
    //关键部分:调用私有的构造方法,让工作经历克隆完成,然后给这个简历的相关字段赋值,最终返回一个深复制的对象
    Resume2 obj = new Resume2(this.work);
    obj.name
    = this.name;
    obj.sex
    = this.sex;
    obj.age
    = this.age;
    return obj;

    }
    }

    小结:                                                                                                        

    原型模式有意思吧

  • 相关阅读:
    JavaScript之链式结构序列化
    js 常用的正则表达式
    99%的人都理解错了HTTP中GET与POST的区别
    取代Promise的Generator生成器函数
    深入了解JavaScript权威指南
    限制input输入类型(多种方法实现)
    textillate.js 文字动画
    jQuery如何改变css伪元素样式
    保存android程序崩溃日志到SD卡
    跟我一起学extjs5(19--模块记录的拖放删除、拖放复制新增)
  • 原文地址:https://www.cnblogs.com/jqbird/p/2145417.html
Copyright © 2020-2023  润新知