争怎路由网/网站教程/内容

我把Black_Cat与Walaqi等对于设计模式之工厂方法抽象工厂的讨论整理如下,以方便设计模式爱好者

网站教程2024-07-09 阅读
工厂方法中如何知道实体产品到底是什么产品呢?
black_cat 发表于 2002-12-10 11:11

虽然模式上说是为了避免客户端知道具体的实体产品。但如果修改了产品的接口,如何能让客户端知道新的接口呢?
比如一个Garden工厂用Create方法创建了两个产品Flower,Glass,都属于抽象产品Plant,但Flower增加了接口Color,而Glass没有该接口,但有另一个接口EverGreenAble。那客户端还是必须根据具体产品来确定该如何工作,但现在客户端只知道是Plant类型,并不知道究竟是哪个产品啊,这种情况怎么办呢?

********************************************************************************在抽象工厂创建新新产品,往往带有较明显的功能取向性的...
epower2002 发表于 2002-12-10 11:22

比如说:
1) 建立一个抽象工厂(Abstract Factory)类HouseFactory,在这个类中声明:
CreateWall ()
CreateDoor ()
CreateFloor ()
CreateCeiling ()
CreatePillar ()
2) 建立相应的抽象产品(Abstract Product)类集:
Wall, Door, Floor, Ceiling, Pillar
3) 为不同风格建立相应的具体工厂(Concrete Factory)类(不要忘了实现关系),例如:
ChinaHouseFactory : HouseFactory
GreeceHouseFactory : HouseFactory

4) 为不同的风格建立相应的具体产品(Concrete Product)类(实现相应的抽象产品),例如:
ChinaWall : Wall
ChinaDoor : Door

GreeceWall : Wall
GreeceDoor : Door

具体请见"简话设计模式"

********************************************************************************工厂方法不知道他所得到的产品的具体类型
walaqi 发表于 2002-12-10 11:41 VB.NET

他只是在一个产品接口上进行操作。
例如:factory的createProduct1()返回一个product1类的实例。
penFactory的createproduct1()返回一个penProduct1类的实例,但是他们都必须满足一个条件,。全部要实现product接口

********************************************************************************这我知道,问题是Product的子类除了实现Product接口外应该还可以定义它们自己的接口呀
black_cat 发表于 2002-12-10 12:09 VB.NET

它们自己的接口就需要根据具体是什么产品来决定了。那么假如要访问各产品自己的接口就必须要知道是什么产品。
刚才我在csdn上问了一下,有人说客户端能判断传入的参数是什么类的(用 product is Flower判断),我不知道是根据什么来判断的?好象tij里说过“上溯造型”“下溯造型”,但我还是没有能透彻得理解,请指教。

********************************************************************************当然可以。
walaqi 发表于 2002-12-11 09:31 VB.NET

一个类可以去实现多个接口。但是其他的接口在你是用工厂模式的场景中是被忽略的。那是另外的事情。
另外,一个类实现多个接口的时候需要需要留意的就是,不要给一个类增加额外的同类名比较模糊的责任。

********************************************************************************被忽略?那样的话是不是就不适合工厂模式了?
black_cat 发表于 2002-12-11 09:49

另外,“不要给一个类增加额外的同类名比较模糊的责任。”是什么意思啊?我高考语文没及格:(

********************************************************************************注意前提:在工厂模式的场景中。
walaqi 发表于 2002-12-11 14:17

所谓工厂模式的场景,就是当客户端掉用工厂方法并获得产品实例的时候,这个时候他只关心产品实例是否实现了产品接口,而不关心产品实例实现的其它接口。
所谓模糊的责任,就是瘦,你建立一个猫的实例,让它实现鸟的接口,那么对于实例的类型名:猫来说,鸟的接口所提供的功能是模糊的。

********************************************************************************那就是说在我的问题中不适合用工厂模式了。
black_cat 发表于 2002-12-11 14:22

是否工厂模式和其他模式结合的应用会有作用?

********************************************************************************模式的结合是经常的。
walaqi 发表于 2002-12-11 14:25

你的问题是什么?

********************************************************************************在主帖中,再贴一遍吧
black_cat 发表于 2002-12-11 14:34

比如一个Garden工厂用Create方法创建了两个产品Flower,Glass,都属于抽象产品Plant,但Flower增加了接口Color,而Glass没有该接口,但有另一个接口EverGreenAble。那客户端还是必须根据具体产品来确定该如何工作,但现在客户端只知道是Plant类型,并不知道究竟是哪个产品啊,这种情况怎么办呢?
-----------------
怎么解决我已经知道了(用plant is Flower),不过我觉得好象脱离了工厂方法的本意了,因为这样客户端就必须要知道确切的产品。不知道这种情况是否超出工厂方法的范畴了。如果一定要用模式的观点去考虑的话可能能用什么模式来解决呢?

********************************************************************************嗬嗬,你对工厂方法的应用没有理解
walaqi 发表于 2002-12-11 14:37

首先,工厂方法只能用于创建一系列功能相近的产品。你的flower和glass完全不相关。这是不能放在一个系列中的。

********************************************************************************这要看分析的粒度了
black_cat 发表于 2002-12-11 14:40

我一开始是从植物的角度分析的。但在设计的过程中又发现粒度需要再细化(这在需求不是很确定或需要增加新的功能的情况下是很正常的),从复用的角度来说也许以上代码大部分都有用,但就是接口需要重新定义,该如何处理呢?

********************************************************************************接口需要重新定义是一个麻烦的问题。
walaqi 发表于 2002-12-11 14:56

接口的作用就是为了保证程序结构的稳定性。如果随意修改接口则无疑对程序造成很不好的影响。
不过看你的样子好像还处在分析阶段?那么你完全可以修改你的接口。
如果已经处于编码阶段。则修改接口可以采用两种方法:
1,定义新的接口
2,修改旧的接口,然后重新编译一边,所有实现该接口的类都会出现类型检查错误,逐一修改,保证所有的对该接口的实现都已经被修改。在重新编译,所有引用了该方法的类也会出现类型检查错误。在修改,就好了。
另外,工厂方法可以接受一个方法,来决定需要返回的产品系列。

********************************************************************************一个系列共享一个产品接口。好像你说的样子必须有两个产品接口
walaqi 发表于 2002-12-11 14:40 VB.NET

另外,仔细阅读一下设计模式书中有关工厂模式的缺点一节。里面有说明。

******************************************************************************** 书上没说什么啊。
black_cat 发表于 2002-12-11 14:46

只是说为了创建一个产品就必须先创建工厂,即使这个工厂除了生产该产品外没有任何用途。
对抽象工厂也只是说如果要添加产品功能就必须要重定义所有的产品接口。

********************************************************************************接口需要重新定义是一个麻烦的问题。
walaqi 发表于 2002-12-11 14:56

接口的作用就是为了保证程序结构的稳定性。如果随意修改接口则无疑对程序造成很不好的影响。
不过看你的样子好像还处在分析阶段?那么你完全可以修改你的接口。
如果已经处于编码阶段。则修改接口可以采用两种方法:
1,定义新的接口
2,修改旧的接口,然后重新编译一边,所有实现该接口的类都会出现类型检查错误,逐一修改,保证所有的对该接口的实现都已经被修改。在重新编译,所有引用了该方法的类也会出现类型检查错误。在修改,就好了。
另外,工厂方法可以接受一个方法,来决定需要返回的产品系列。

********************************************************************************
我觉得最可怕的问题是需求分析时没考虑到,但完成编码时才知道不对。
black_cat 发表于 2002-12-11 15:07 VB.NET

另外,在写程序时如何尽量为以后的升级留好接口,这点可能需要对程序以后要实现的功能也要作一个比较清晰的分析,就是在写ver1.0的时候要考虑到ver2.0以后的使用需求状况。这点也很难。斑竹以为然否?

********************************************************************************
任何人都不可能预知未来
walaqi 发表于 2002-12-11 20:47

即便是一个经验丰富足智多谋的设计师也不可能预知未来,为将来的可能出现的需求定义良好的接口。
设计模式正是为了满足这个需要而诞生的,但是设计模式也只是部分的解决了这个问题。学习设计模式的最终目的,其实不是为了学习设计模式所讲述的方法,而是学习他为了扩展而对结构做出设计的过程和方法。例如工厂模式,将一些操作延迟到了其子类,那么就给将来扩展这些方法留下了一个渠道:通过继承产生子类来扩展逻辑。但是当你需要使用的产品具有了较大差异,无法在归属于同一个接口的时候,工厂方法也就不再适用了。
另一个解决需求变更以及扩展的办法就是对尽量完备的应用场景进行提炼(也就是预计一下自己公司在现在和将来可能要处理的各种场景),定义一个较为完善和相对稳定的架构。这个架构可以在迭代中被不断使用,并提供一定数量的扩展的方法。但是架构在很大程度上限制了程序的灵活性,所有的需求被分析的思路必须符合架构的要求。
所以,没有一劳永逸的办法。如果要解决有关扩展的话题,我觉得最佳的办法就是:使用设计模式的思想,建立一个完善的架构,然后再使用过程中对这个架构进行小心翼翼的重构。则可以解决绝大多数的问题。

********************************************************************************
有道理,也许这就是有经验的系统分析师与普通的coder之间的区别。
black_cat 发表于 2002-12-12 13:40

一般的程序员总是拿到项目就开始想该如何实现这个项目。能一开始就从可复用的角度思考的人是很少的,而能分析得很完善的则少之又少。也难怪,需求总是不断变化的,很少能有程序能自动适应所有的需求。但如果考虑的比较周到的话以后升级起来非常方便。谢谢斑竹的指点:)



……

相关阅读