随笔-112  评论-610  文章-5  trackbacks-16
    他也有讲错的时候,虽然只是一点点,但还是被我抓到了,呵呵。而且通过对错误地方分析可以知道,错因是他对OOD基本原则的理解以及对Abstract Factory的理解似乎还不是十分到位。
    看得出,他讲《设计模式》的蓝本是英文版的GoFDesign Patterns》,课件上都是清一色的英文,对每一个DP的介绍模式也都是按照GoF那本书来的。但是他今天在讲到抽象工厂局限性的时候,用红色字体打出:
    difficult to ... new kinds of objectsp.s.原话记不清了)
    然后解释说:抽象工厂的局限性就在于当有新的产品线3需要加入系统的时候,不但要新建继承自AbstractProcuctAProductA3类,新建继承自AbstractProcuctBProductB3类,“这倒没有什么”,而且还要新建一个集成自AbstractFactoryConcreteFactory3,“这就不行了”。从他的语气中可以知道他认为新建类,特别是要新建一个具体工厂是“不好”的。
    然而就我目前对DP的理解,情况却不是这样的。当有产品线3需要加入系统时,正好是抽象工厂显示威力的时候。新增加的三个派生类ProductA3ProductB3ConcreteFactory3很好的展示了抽象工厂模式符合“开放-封闭原则”的特点——新的需求没有对原有的设计和结构,特别是AbstractFactoryAbstractProductX接口做任何的修改,只是对现有系统进行了扩展,就实现了新的需求。而对“增加新的产品线//系列”这个轴线上的需求变化的应对自如也正是抽象工厂的力量所在。
    那么对于GoF书中的那句“difficult to ... new kinds of objects”怎么理解呢?
    抽象工厂的局限性应该是当需求变化的轴线在于“增加组成系统的新产品/对象”的时候,就力不从心了。
    这里就拿老师上课举的例子来说明。他的例子是构建一个迷宫游戏(Maze Game),组成迷宫(Maze)的基本元素有三个
——房间(room)、墙壁(wall)和门(door)。游戏分为不同的难度等级,比如easy/normal/hard,对应于不同的难度,房间、墙壁和门是不同的,比如hard模式的门可能是带有密码锁的。其实这个例子看起来并不十分恰当,因为通常应该觉得迷宫的难度等级应该按照其内部的复杂度来划分,而不是按照他的这种方式来划分,这个暂且不管,就先用他的划分方式吧。场景,比如丛林迷宫、楼房迷宫等等。在这些不同的场景下,房间、墙壁和门的风格当然也是不同的,所以这里应用抽象工厂是一个合适的选择。
// AbstractFactory
public abstract class MazeFactory
{
    
abstract Room CreateRoom();
    
abstract Wall CreateWall();
    
abstract Door CreateDoor();
}

// ConcreteFactory1
public class JungleMazeFactory : MazeFactory
{
    
public override Room CreateRoom(){}
    
public override Wall CreateWall(){}
    
public override Door CreateDoor(){}
}

// ConcreteFactory2
public class BuildingMazeFactory : MazeFactory
{
    
public override Room CreateRoom(){}
    
public override Wall CreateWall(){}
    
public override Door CreateDoor(){}
}


// AbstractProductA
public abstract class Room
{}

// AbstractProductB
public abstract class Wall
{}

// AbstractProductC
public abstract class Door
{}

// ProductA1
public class JungleRoom : Room
{}

// ProductA2
public class BuildingRoom : Room
{}

// ProductB1
public class JungleWall : Wall
{}

// ProductB2
public class BuildingWall : Wall
{}

// ProductC1
public class JungleDoor : Door
{}

// ProductC2
public class BuildingDoor : Door
{}
    现在如果需求发生变化,需要一种新的迷宫场景,比如海底迷宫(SeabedMaze),而迷宫的基本组成元素仍然是房间、墙壁和门,那么我只需要对原有系统做如下扩展
// ConcreteFactory3
public class SeabedMazeFactory : MazeFactory
{
    
public override Room CreateRoom(){}
    
public override Wall CreateWall(){}
    
public override Door CreateDoor(){}
}


// ProductA3
public class SeabedRoom : Room
{}

// ProductB3
public class SeabedWall : Wall
{}

// PruductC3
public class SeabedDoor : Door
{}
    然后client就可以生成通过传入SeabedMazeFactory的对象实例来创建这个海底场景的迷宫了,原有的逻辑都可以不动,这样就算是再来几个空中迷宫、地下迷宫什么的,只要是迷宫的基本组成三要素——房间、墙壁和门不变,我就可以通过不断的对现有系统进行扩展来达到目的,哈,太完美了。
    但是,如果这时需求朝着另一个方向变化——迷宫中需要加入新的元素,比如陷阱、楼梯、地道……——那就完蛋了。如果还是单单通过扩展现有系统就达不到目的了。原因就在于ProductAProductB...增加了,而AbstractFactory,或者说是MazeFactory中只有CreateRoom()CreateWall()CreateDoor()抽象方法,而如果要加入对陷阱、楼梯、地道……的支持,则必须要修改MazeFactory这个AbstractFactory的接口,而这显然是不希望看到的,也是违背“开-闭原则”的。
    抽象工厂的局限性就在于此。

    那GoF的话说错了吗?请注意,人家说的可是“new kinds of objects”,而不是“new families of objects”,一字之差,含义完全不同。老师把GoF的意思理解成了后者,而后者不但不是抽象工厂的劣势,反而恰恰是其优势所在。前者才真正是抽象工厂的软肋。

    这里又想到一个事情,我还是觉得GoF那本书不太适合做入门读物,更不太适合做教材,但是这学期的课上老师推荐的书只有三本,第一本就是这个,唉~~我觉得这本小册子会挡住很多对DP有热情但又缺乏实践经验的初学者的。
posted on 2006-03-30 16:31 合金枪头 阅读(1778) 评论(8)  编辑 收藏 所属分类: Design Patterns

评论:
#1楼  2006-03-31 00:57 | aspnetx      
支持
我们学校的老师绝对比你说到的还白痴
讲面向对象的时候会给你两中感觉:一听着好累,而,好想扁人
  回复  引用  查看    
#2楼  2006-03-31 01:08 | wen3062 [未注册用户]
我们学校的老师根本不讲~
  回复  引用    
#3楼  2006-03-31 01:31 | jackyrong的世界      
看<<head first design pattern>>吧
  回复  引用  查看    
#4楼  2006-03-31 03:14 | bengxia      

个人感觉设计模式通过讲课确实很难说清,还是得静下心来实践+思考。有点只可意会,不能言传的悬乎。学习优秀的代码能掌握不少,还是不要刻意去搬套。

另外,楼上的小弟未成年吧。
  回复  引用  查看    
#5楼  2006-03-31 03:57 | POLARIS      
只是明白别人讲的不是,真正的理解。
真正的理解,需要实践,需要发表,需要很多...
  回复  引用  查看    
#6楼 [楼主] 2006-04-02 03:47 | 合金枪头      
@aspnetx
我们的这个老师课讲的还是很不错的,但估计他也没有在实际工程中广泛的应用DP,这也可以理解。不过其他更垃圾的讲课的人我这也有不少,纯粹是骗课时费。

@jackyrong的世界
《Head First》那本书我手里有电子版,印刷版我一直在犹豫到底买不买,也曾去过书店,但是由于出版社太怪异——东南大学——我们这里的书店基本都不跟他合作,所以也只能作罢。而且DP的书我也有好几本了,暂时就先看这些吧,特别推荐的是《Design Patterns Explained》现在刚出了第二版。

@bengxia
你说的对,DP是从实践中来的经验,自然也应该回归实践。讲课+听课的方式一直就是我比较反感的信息传播方式,授课者的表达方式可能就已经把知识打了一次折,听课者在理解的时候又打了一次折,所以最终的效率是很低的,特别是这种以实践为基础的课。
p.s.原来你楼上的苍蝇已经轰走

@POLARIS
能体会到这种级别的老师(他也算是我们学校的金牌教授了,这课也是他们学院研究生的核心课,DP只是其中的一个专题)在这种层面上的一点点偏差应该也算是“真正的理解”的一个阶段吧:)
  回复  引用  查看    
#7楼  2006-09-08 02:42 | wayne1017      
貌似你听到这个错误以后就走人再也不去听他的课了吧?呵呵
  回复  引用  查看    
#8楼 [楼主] 2006-09-08 10:00 | 合金枪头      
@wayne1017
-_-!这都被你发现了……
  回复  引用  查看