动机
框架使用抽象类定义和维护对象之间的关系。这些对象的创建通常也由框架负责。
面向对象编程很多场合其实就是对抽象类编程。我们可以认为,抽象类+抽象类之间的协作构成了架构。在这样的架构中,通常也会包含对象的创建部分。
考虑这样一个应用框架,它可以向用户显示多个文档。在这个框架中,两个主要的抽象是类Application和Document。这两个类都是抽象的,客户必须通过它们的子类来做与具体应用相关的实现。例如,为创建一个绘图应用,我们定义类DrawingApplication和DrawingDocument。Application类负责管理Document并根据需要创建它们 — 例如,当用户从菜单中选择Open或New的时候。
这个例子,可以参考Office。Excel和Word的具体操作有很大的不同,但是如果从抽象的角度来看,Word和Excel都可以看作Application,而Word文档和Excel文档都可以抽象为Document。有了这样的观点之后,文件打开,关闭,保存,内容拷贝,粘贴等操作就构成了微软的应用程序开发架构。有了这个架构之后,就可以利用它开发自己的应用,例如绘图软件。这是由于大量的共通部分已经完成,开发者只要根据具体的需求提供相应的具象类就可以很快地开发出自己的应用了。
用户通过应用菜单选择打开或创建文件时,架构(实际上是Application)有义务创建相应的对象。
因为被实例化的特定Document子类是与特定应用相关的,所以Application类不可能预测到哪个Document子类将被实例化 —Application类仅知道一个新的文档何时应被创建,而不知道哪一种Document将被创建。这就产生了一个尴尬的局面:框架必须实例化类,但是它只知道不能被实例化的抽象类。
由于架构代码都是先于应用构建的,所以抽象的Application不可能知道具象的Document类的类型。也就是说架构需要实例化某些类,却不知道实际需要实例化的类型。
Factory Method模式提供了一个解决办案。它封装了哪一个Document子类将被创建的信息并将这些信息从该框架中分离出来,如下页上图所示。
为了解决这个问题,工厂方法模式提供了一种将创建具象Document类的部分从架构中分离出来的方法。
Application的子类重定义Application的抽象操作CreateDocument以返回适当的Document子类对象。一旦一个Application子类实例化以后,它就可以实例化与应用相关的文档,而无需知道这些文档的类。我们称CreateDocument是一个工厂方法(factorymethod),因为它负责“生产”一个对象。
首先在抽象Application类中定义抽象操作返回抽象Document的CreateDocument操作并在架构中使用。在开发具体应用时实现一个构建具象Document的具象Acpplication类并将其引入架构中。这个创建对象的方法就是工厂方法。
作者观点
古语有云:兵无常势,水无常形。我们可以说设计模式的运用场景多种多样,各有不同;但是古语也说万变不离其宗,设计模式的出发点其实还真就没有那么玄乎,只要真正领会多态的内涵,正确识别抽象和具体,变与不变,很多事情其实都是水到渠成的事情。
首先对基类(或者说抽象类)编程,然后通过组装的方式导入具象类可以说是所有架构的共同方式。
注:
本文中
蓝 {MOD}粗体文字都引自《设计模式》一书。
觉得本文有帮助?请分享给更多人。
阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】