• 设计模式笔记——原型模式(Prototype Pattern)


    一、概述

    和工厂模式一样,同样对客户隐藏了对象创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过copy一个现有对象来生产新对象的。

    二、原型模式

    原型模式的一种形式是带原型管理器的原型模式,其类图如下:

     

    客户(Client)角色:客户端类向原型管理器提出创建对象的请求。

    抽象原型(Prototype)角色:这是一个抽象角色,通常由一个C#接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在C#中,抽象原型角色通常实现了ICloneable接口。

    具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

    原型管理器(Prototype Manager)角色:创建具体原型类的对象,并记录每一个被创建的对象。

    三、示例(1)

    我们用混合调色板管理招式来为大家演示原型模式:假定调色板的每种颜色都是有红绿蓝三种基础颜色搭配出来,使用前将各种颜色搭配出来,用户使用时只需要选定你需要的颜色名称便可得到相应的颜色。

    1.首先我们需要抽象原型(Prototype)角色:ColorPrototype

    abstract public  class ColorPrototype
        {
             public abstract ColorPrototype clone();
        }

    2.然后我们添加具体原型(Concrete Prototype)角色:Color(这里我们使用浅拷贝shallow copy方式)

        public class Color:ColorPrototype
        {
            private int red;
            private int green;
            private int blue;
    
            public Color(int red,int green,int blue)
            {
                this.red = red;
                this.green = green;
                this.blue = blue;
            }
    
            //Shallow Clone
            public override ColorPrototype clone()
            {
                return (ColorPrototype)this.MemberwiseClone();
            }
    
            public void Display()
            {
                Console.WriteLine("RGB is:{0},{1},{2}",red,green,blue);
            
            }
        }

    3.我们还需要原型管理器(Prototype Manager)角色:PrototypeManager

     

    public class PrototypeManager
        {
            Hashtable colors = new Hashtable();
            public ColorPrototype this[string name]
            {
                get { return (ColorPrototype)colors[name]; }
                set { colors.Add(name, value); }
            }
        }

     

    4.最后我们来实现客户端代码

     

    static void Main(string[] args)
            {
                PrototypeManager manager = new PrototypeManager();
                manager["red"] = new Color(255, 0, 0);
                manager["green"] = new Color(0, 255, 0);
                manager["blue"] = new Color(0, 0, 255);
                manager["angry"] = new Color(255, 54, 0);
                manager["peace"] = new Color(128, 211, 128);
                manager["flame"] = new Color(211, 34, 20);
                string colorname = "red";
                Color color = (Color)manager[colorname].clone();
                color.Display();
                colorname = "flame";
                color = (Color)manager[colorname].clone();
                color.Display();
                colorname = "angry";
                color = (Color)manager[colorname].clone();
                color.Display();
            }

     

    四、示例(2)

    在C#里面,我们可以很容易的通过Clone()方法实现原型模式。任何类,只要想支持克隆,必须实现C#中的ICloneable接口。ICloneable接口中有一Clone方法,可以在类中复写实现自定义的克隆方法。克隆的实现方法有两种:浅拷贝(shallow copy)与深拷贝(deep copy)。浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。而深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式,所以如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个深拷贝的话,我们将创建一个新的对象和一个新的字符串--新对象将引用新字符串。需要注意的是执行深拷贝后,原来的对象和新创建的对象不会共享任何东西;改变一个对象对另外一个对象没有任何影响。

    下面让我们了解一下浅拷贝(shallow copy)与深拷贝(deep copy)的区别:

    1.实现浅拷贝(shallow copy)代码:

    public class ShallowCopy
        {
            public string[] ShallowObject = { "1", "2", "3" };
    
            public Object Clone()
            {
                return this.MemberwiseClone();
            }
    
            public void Display()
            {
                foreach (string i in ShallowObject)
                {
                    Console.Write(i + ", ");
                }
    
                Console.WriteLine();
            }
        }


    2.实现深拷贝(deep copy)代码:

        public class DeepCopy : ICloneable
        {
            public string[] deepObject = { "1", "2", "3" };
            private DeepCopy(string[] deepObject)
            {
                this.deepObject = (string[])deepObject.Clone();
            }
            public Object Clone()
            {
                return new DeepCopy(this.deepObject);
            }
            public void Display()
            {
                foreach (string i in deepObject)
                {
                    Console.Write(i + ", ");
                }
                Console.WriteLine();
            }
        }


    3.执行结果:

    9 , 2 , 3

    9 , 2 , 3

    9 , 2 , 3

    1 , 2 , 3

     

    五、分析Prototype模式的优缺点(摘自http://www.cnblogs.com/zhenyulu/articles/39257.html

      Prototype模式的优点包括

       1)Prototype模式允许动态增加或减少产品类。由于创建产品类实例的方法是产批类内部具有的,因此增加新产品对整个结构没有影响。

         2)Prototype模式提供了简化的创建结构。工厂方法模式常常需要有一个与产品类等级结构相同的等级结构,而Prototype模式就不需要这样。

         3)Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。

         4)产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构。

      Prototype模式的缺点:

      Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,

      但对已有的类进行改造时,不一定是件容易的事。

     

  • 相关阅读:
    js实现页面跳转,location.href和location.replace和location.reload的区别
    Object.create()和new 创建对象的区别
    apply、call、bind区别、用法
    JavaScript toString() 函数详解
    javascript中this指针详解
    javascript中null 和 undefined的区别
    jQuery 图片轮流展示效果
    min-height 兼容
    css 命名规范
    移动端隐藏手机虚拟键盘
  • 原文地址:https://www.cnblogs.com/Abel-Zhang/p/PrototypePattern.html
Copyright © 2020-2023  润新知