第十七章 兰州拉面馆——原型模式
17.1 兰州拉面馆
时间:1月2日 地点:兰州拉面馆 人物:大B,小A
这天大B出去办事,中午经过小A学校,正好约小A出来吃饭。
大B:“出来校门口,我请你吃饭。”
小A:“好。”
大B:“想吃什么?”
小A:“简单点好。对了,我们校门口那家兰州拉面馆很不错喔!你不是也喜欢吃面吗?我们去试一下?”
大B:“嘿嘿!不错喔!”
小A:“兰州拉面馆有牛肉拉面(大碗 )、牛肉拉面(小碗)、牛肉刀削面、羊肉拉面、羊肉刀削面。”
大B:“嘿嘿!什么都好。我出来办事,肚子饿了喔!”
小A:“嘿嘿!如果说要吃手擀面、挂面、珍珠翡翠鲍鱼面,恐怕没有喔!”
大B:“别啦!随便就好。”
17.2 原型模式
牛肉拉面,牛肉刀削面等可以看作是原型,面馆可以看作是原型管理器。原型模式在创建对象不是直接创建的,也就是说,不是通过外部调用类的构造函数调用的,而是通过已存在的对象实例克隆出一个对象,这个克隆对象和他的源对象具有相同的属性和状态,也就是说面馆里的牛肉刀削面每一碗状态都是一样的。
大B:“你现在知不知道什么是原型模式?”
小A:“有点意识。但不是很清楚。”
大B:“原型模式是允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。”
小A:“原型模式有什么意图?”
大B:“用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。”
参考图17-1原型模式结构图:
图17-1 原型模式结构图
17.3 原型模式应如何使用?
小A:“师兄,原型模式应该如何使用?”
大B:“因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单。”
以勺子为例:
有两个具体实现(ConcretePrototype):
调用Prototype模式很简单:(www.xing528.com)
AbstractSpoon spoon = new SoupSpoon();
AbstractSpoon spoon = new SaladSpoon();
当然也可以结合工厂模式来创建AbstractSpoon实例。
在Java中Prototype模式变成clone()方法的使用,由于Java的纯洁的面向对象特性,使得在Java中使用设计模式变得很自然,两者已经几乎是浑然一体了。
17.4 为什么需要原型模式?
小A:“为什么需要原型模式?”
大B:“引入原型模式的本质在于利用已有的一个原型对象,快速的生成和原型对象一样的实例。你有一个A的实例a:A a = new A();现在你想生成和car1一样的一个实例b,按照原型模式,应该是这样:A b = a.Clone();而不是重新再new一个A对象。通过上面这句话就可以得到一个和a一样的实例,确切的说,应该是它们的数据成员是一样的。Prototype模式同样是返回了一个A对象而没有使用new操作。”
17.5 原型模式的优点和缺点
小A:“原型模式有什么优点吗?”
大B:“原型模式的优点:1、Prototype模式允许动态增加或减少产品类。由于创建产品类实例的方法是产批类内部具有的,因此增加新产品对整个结构没有影响。2、Prototype模式提供了简化的创建结构。工厂方法模式常常需要有一个与产品类等级结构相同的等级结构,而Prototype模式就不需要这样。3、Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。4、产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构。”
小A:“原型模式又有些什么缺点呢?”
大B:“原型模式的缺点:每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。”
17.6 原型模式满足了哪些面向对象的设计原则?
小A:“师兄,原型模式满足了哪些面向对象的设计原则?”
大B:“依赖倒置原则:上面的例子,原型管理器(ColorManager)仅仅依赖于抽象部分(ColorPrototype),而具体实现细节(ConcteteColorPrototype)则依赖与抽象部分(ColorPrototype),所以Prototype很好的满足了依赖倒置原则。”
17.7 原型模式实现要点
小A:“原型模式实现要点有哪些?”
大B:“1、使用原型管理器,体现在一个系统中原型数目不固定时,可以动态的创建和销毁,2、实现克隆操作,在.NET中可以使用Object类的MemberwiseClone()方法来实现对象的浅表拷贝或通过序列化的方式来实现深拷贝。3、Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些‘易变类’拥有稳定的接口。”
17.8 原型模式适用性
小A:“什么情况下,应当使用原型模式?”
大B:“1、当一个系统应该独立于它的产品创建,构成和表示时;2、当要实例化的类是在运行时刻指定时,例如,通过动态装载;3、为了避免创建一个与产品类层次平行的工厂类层次时;4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。”
原型模式同工厂模式,同样对客户隐藏了对象的创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的,达到了‘隔离类对象的使用者和具体类型(易变类)之间的耦合关系’的目的。
17.9 克隆对象分为浅拷贝和深拷贝
小A:“克隆对象有哪些?”
大B:“克隆对象分为浅拷贝和深拷贝。我给你详细讲一下。浅拷贝就是克隆的对象和它的源对象共享引用的对象,举个例子,可能不恰当,假设牛肉刀削面引用一个对象:Money,表示它值多少钱,这里说的对象是说它是System.Object继承的(c#), 也就是说不同的浅拷贝对象,他们的价钱是一样的,当克隆对象的价钱变过之后,它所引用的对象的价钱也就随之改变了,比如面馆。调低了牛肉刀削面的价格,由5块钱调到了4块钱,那么每碗面的价格都变到了四块钱。但对值类型而言,每个浅拷贝对象都有自己的拷贝,也就是说,当改变克隆对象的值类型时,它的源对象相应属性不会改变。深拷贝就是完全的拷贝。不仅值类型有自己的拷贝,连引用对象也有自己的一份拷贝,修改克隆对象的任何属性,也不会对源对象产生任何影响。原型管理器,就是提供原型注册使用,当创建对象使,可以使用里面的对象进行克隆,当有新的实例对象时,也可以将他们加到原型管理器里。说的有点乱,程序员,还是用代码交流最好。”
下面的程序分别实现了原型克隆时浅拷贝和深拷贝。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。