设计模式可复用面向对象软件的基础 第3章 创建(7)
发布时间:2021-06-05
发布时间:2021-06-05
本书设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好,表达清楚的软件设计模式,这些模式在实用环境下有特别有用
如果有多个可能的产品系列,具体工厂也可以使用 P r o t o t y p e(3 . 4)模式来实现。具体工厂使用产品系列中每一个产品的原型实例来初始化,且它通过复制它的原型来创建新的产品。在基于原型的方法中,使得不是每个新的产品系列都需要一个新的具体工厂类。
此处是S m a l l t a l k中实现一个基于原型的工厂的方法。具体工厂在一个被称为 p a r t C a t a l o g的字典中存储将被复制的原型。方法 m a k e:检索该原型并复制它:
make : partName ^ (partCatalog at : partName) copy
具体工厂有一个方法用来向该目录中增加部件。
addPart : partTemplate named : partName partCatalog at : partName put : partTemplate
原型通过用一个符号标识它们,从而被增加到工厂中:
aFactory addPart : aPrototype named : #ACMEWidget
在将类作为第一类对象的语言中(例如 S m a l l t a l k和O b j e c t i v e C),这个基于原型的方法可能有所变化。你可以将这些语言中的一个类看成是一个退化的工厂,它仅创建一种产品。你可以将类存储在一个具体工厂中,这个具体工厂在变量中创建多个具体的产品,这很像原型。这些类代替具体工厂创建了新的实例。你可以通过使用产品的类而不是子类初始化一个具体工厂的实例,来定义一个新的工厂。这一方法利用了语言的特点,而纯基于原型的方法是与语言无关的。
像刚讨论过的 S m a l l t a l k中的基于原型的工厂一样,基于类的版本将有一个唯一的实例变量p a r t C a t a l o g,它是一个字典,它的主键是各部分的名字。 p a r t C a t a l o g存储产品的类而不是存储被复制的原型。方法m a k e:现在是这样:
make : partName ^ (partCatalog at : partName) new
3) 定义可扩展的工厂 A b s t r a c t F a c t o r y通常为每一种它可以生产的产品定义一个操作。产品的种类被编码在操作型构中。增加一种新的产品要求改变 A b s t r a c t F a c t o r y的接口以及所有与它相关的类。一个更灵活但不太安全的设计是给创建对象的操作增加一个参数。该参数指定了将被创建的对象的种类。它可以是一个类标识符、一个整数、一个字符串,或其他任何可以标识这种产品的东西。实际上使用这种方法, A b s t r a c t F a c t o r y只需要一个“ M a k e”操作和一个指示要创建对象的种类的参数。这是前面已经讨论过的基于原型的和基于类的抽象工厂的技术。
C + +这样的静态类型语言与相比,这一变化更容易用在类似于 S m a l l t a l k这样的动态类型语言中。仅当所有对象都有相同的抽象基类,或者当产品对象可以被请求它们的客户安全的强制转换成正确类型时,你才能够在 C + +中使用它。Factory Method(3.3)的实现部分说明了怎样在C + +中实现这样的参数化操作。
该方法即使不需要类型强制转换,但仍有一个本质的问题:所有的产品将返回类型所给定的相同的抽象接口返回给客户。客户将不能区分或对一个产品的类别进行安全的假定。如果一个客户需要进行与特定子类相关的操作,而这些操作却不能通过抽象接口得到。虽然客户可以实施一个向下类型转换( d o w n c a s t)(例如在C + +中用d y n a m i c _ c a s t),但这并不总是可行或安全的,因为向下类型转换可能会失败。这是一个典型的高度灵活和可扩展接口的权衡 折衷。
上一篇:WSUS服务器的迁移
下一篇:特种加工论文