设计模式原型模式(Prototype)- 面馆里的菜单

类别:.NET开发 点击:0 评论:0 推荐:

设计模式-原型模式

 

参考资料

《c#技术揭密》

《设计模式-可复用面向对象软件的基础》

《java与模式》

http://blog.csdn.net/beautyispower/ ,很不错的网友blog

 

很多餐馆里面都有菜单,列举了他们提供哪些饭菜,哪种面食等,一般的兰州拉面馆里菜单是这样的

牛肉拉面(大碗 )

牛肉拉面(小碗)

牛肉刀削面

羊肉拉面

羊肉刀削面

你到了这里,你说我要吃手擀面,我要吃挂面,我要吃珍珠翡翠鲍鱼面,他恐怕没有,这些面就需要定

制,上面说的牛肉拉面,牛肉刀削面等可以看作是原型,面馆可以看作是原型管理器。

原型模式在创建对象不是直接创建的,也就是说,不是通过外部调用类的构造函数调用的,而是通过

已存在的对象实例克隆出一个对象,这个克隆对象和他的源对象具有相同的属性和状态,也就是说面馆里的

牛肉刀削面每一碗状态都是一样的。

克隆对象分为浅拷贝和深拷贝

浅拷贝就是克隆的对象和它的源对象共享引用的对象,举个例子,可能不恰当,假设牛肉刀削面引用一个对象:Money,表示它值多少钱,这里说的对象是说它是System.Object继承的(c#), 也就是说不同的浅拷贝对象,他们的价钱是一样的,当克隆对象的价钱变过之后,它所引用的对象的价钱也就随之改变了,比如面馆

调低了牛肉刀削面的价格,由5块钱调到了4块钱,那么每碗面的价格都变到了四块钱。但对值类型而言,每个浅拷贝对象都有自己的拷贝,也就是说,当改变克隆对象的值类型时,它的源对象相应属性不会改变。

深拷贝就是完全的拷贝

不仅值类型有自己的拷贝,连引用对象也有自己的一份拷贝,修改克隆对象的任何属性,也不会对源对象产生任何影响。

原型管理器,就是提供原型注册使用,当创建对象使,可以使用里面的对象进行克隆,当有新的实例对象时,也可以将他们加到原型管理器里。

说的有点乱,程序员,还是用代码交流最好,下面的程序分别实现了原型克隆时浅拷贝和深拷贝。

//
//理解深拷贝和浅拷贝
//
//浅表副本创建与原始对象具有相同类型的新实例,然后复制原始对象的非静态字段。
//如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制该
//引用但不复制被引用的对象;这样,原始对象中的引用和复本中的引用指向同一个对象。
//相反,对象的深层副本复制对象中字段直接或间接引用的全部内容。
//
//例如,如果 X 是一个具有对对象 A 和对象 B 的引用的 Object,并且对象 A 还具
//有对对象 M 的引用,则 X 的浅表副本是对象 Y,而 Y 同样具有对对象 A 和对象 B
//的引用。相反,X 的深层副本是对象 Y,而对象 Y 具有对对象 C 和对象 D 的直接引
//用以及对对象 N 的间接引用,其中 C 是 A 的副本,D 是 B 的副本,而 N 是 M 的副本。

using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Data;

namespace Prototype
{
     /// <summary>
     /// Prototype类型实例
     /// </summary>
     class TestPrototypeApp
     {
          /// <summary>
          /// 应用程序的主入口点。
          /// </summary>
          [STAThread]
      static void Main(string[] args)
      {

           //定义原型管理器
           NoodleManager noodleManager=new NoodleManager();
   
           //客户要求下面三碗面
           Noodle beefNoodle=(Noodle)noodleManager["牛肉拉面"].Clone();

          // Noodle beefNoodle=(Noodle)noodleManager["牛肉拉面"].DeepClone();
           Noodle muttonNoodle=(Noodle)noodleManager["羊肉拉面"].Clone();
           Noodle beefCutNoodle=(Noodle)noodleManager["牛肉刀削面"].Clone();

           //修改克隆对象中的引用对象的属性,验证它是浅拷贝还是深拷贝
           beefNoodle.TbName=",哈哈哈!,克隆对象改名了,你改不改";

           //显示原始对象的NoodelName和TbName 
           Console.WriteLine(noodleManager["牛肉拉面"].NoodleName+noodleManager["牛肉拉面"].TbName+"\n");
           //显示克隆对象的NoodleName和TbName
           Console.WriteLine(beefNoodle.NoodleName+beefNoodle.TbName+"\n");

  
           //将新的产品加入原型管理器,以备以后克隆时使用,下面是定义了一种新的面条-羊肉刀削面,

           //并把它添加到面条管理器中,如果以后再有客户点这个面,直接克隆即可。
           noodleManager["羊肉刀削面"]=new CutNoodle("羊肉刀削面");

           //克隆一碗羊肉刀削面
           Noodle muttonCutNoodle=(Noodle)noodleManager["羊肉刀削面"].Clone();

           Console.WriteLine(noodleManager["羊肉刀削面"].NoodleName+"\n");
           Console.WriteLine(muttonCutNoodle.NoodleName+"\n");

           Console.ReadLine();
   
      }
 }

 

 

 //抽象产品-面条
 //序列化属性,为深拷贝时使用,每个派生类都要加上此属性才能实现深拷贝
 [Serializable]
 public abstract class Noodle
 {
      //定义一个DataTable对象,主要是为了验证对比类中含有引用对象时的深拷贝和浅拷贝时的不同,

     //你也可以采用别的任何引用对象   
      protected DataTable dataTable=new DataTable();
      public string TbName
      {
           get{return dataTable.TableName;}
           set{dataTable.TableName=value;}
      }

      //字段
      protected string noodleName;
      //特性
      public string NoodleName
      {
           get{return noodleName;}
           set{noodleName=value;}
      }

          public abstract Noodle Make(string name);
          //浅克隆的接口
          public abstract Noodle Clone();
          //深克隆的接口
          public abstract Noodle DeepClone();
 }

 //具体产品,拉面
 
 [Serializable]
 public class  PullNoodle:Noodle
 {

     public PullNoodle(string name)
      {
           this.NoodleName=name;
           this.TbName=name+"table";
           Console.WriteLine("PullNoodle is made\n");
      }

      //实现浅拷贝
      public override Noodle Clone()
      {
           return (Noodle)this.MemberwiseClone();
      }

      //实现深拷贝,“淹咸菜”的过程,先将对象序列化到内存流,再反序列化,即可得到深克隆
      public override Noodle DeepClone()
      {
           //定义内存流
           MemoryStream ms=new MemoryStream();
           //定义二进制流
           IFormatter bf=new BinaryFormatter();
           //序列化
           bf.Serialize(ms,this);
           //重置指针到起始位置,以备反序列化
           ms.Position=0;
           //返回反序列化的深克隆对象
           return (Noodle)bf.Deserialize(ms);

      }


      public override Noodle Make(string name)
      {
           return new PullNoodle(name);
      }

 }

 //具体产品-刀削面
 [Serializable]
 public class CutNoodle:Noodle
 {
      public CutNoodle(string name)
      {
           this.NoodleName=name;
           this.TbName=name+"table";
           Console.WriteLine("CutNoodle is made\n");
      }

  //实现浅克隆
      public override Noodle Clone()
      {
           return (Noodle)this.MemberwiseClone();
      }

      public override Noodle Make(string name)
      {
           return new CutNoodle(name);
      }
  //实现深克隆
      public override Noodle DeepClone()
      {
           MemoryStream ms=new MemoryStream();
           IFormatter bf=new BinaryFormatter();
           bf.Serialize(ms,this);
           ms.Position=0;
           return (Noodle)bf.Deserialize(ms);

      }
 }

 //定义原型管理器,用于存储原型集合,这里采用的是HashTable
 
 class NoodleManager
 {
      //定义HashTable
      protected Hashtable noodleHt=new Hashtable();
      protected Noodle noodle;

      public NoodleManager()
      {

      //初始化时加入三种基本原型
       noodle=new PullNoodle("牛肉拉面");
       noodleHt.Add("牛肉拉面",noodle);
       noodle=new PullNoodle("羊肉拉面");
       noodleHt.Add("羊肉拉面",noodle);
       noodle=new CutNoodle("牛肉刀削面");
       noodleHt.Add("牛肉刀削面",noodle);

      }
      //索引器,用于添加,访问Noodle对象
      public Noodle this[string key]
      {
           get{ return (Noodle)noodleHt[key];}
           set{ noodleHt.Add(key,value);}
      }

 }


}

本文地址:http://com.8s8s.com/it/it42382.htm