设计模式笔记——原型模式(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模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,

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

 

原文地址:https://www.cnblogs.com/Abel-Zhang/p/PrototypePattern.html