`

工厂模式与OO设计原则

阅读更多
如果把创建看作一个职责,那么系统中的哪个对象应该拥有这个职责呢?如果把创建看作知识,那么创建知识应该放置在什么地方呢?说到职责我们不得不说一下著名的GRASP原则:

  GRASP是通用职责分配软件模式(General Responsibility Assignment Software patterns)的简称。它包含了9大模式,分别如下所示:

  1 创建者(Creator) :决定对象应该有谁来创建的问题。

  2 信息专家(Information expert):用此模式来确定如何给对象分配职责的问题。一般把职责分配给那些包含此职责有关信息的对象。这样也体现了高内聚性模式。

  3 低耦合(Low coupling)

  4 控制器(Controller).

  5 高内聚(High Cohesion)

  6 多态性(polymorphism)

  7 纯虚构(pure fabrication)

  8 间接性(indirection)

  9 防止变异(protected variations)

  可以看出GRASP非常关注对象由谁来创建,并给出了一个职责分配的解决模型:信息专家模式;我们不必深究GRASP的种种细节,我们从上面的表述中可以得到这样的启示:

  对象的创建不是随意性的,也是有规范可以遵循的,我们可以从中得到灵活性和可维护性;
  职责分配给这个职责相关的信息专家,即:最适合的人做最适合的事情
  当创建一个对象的知识散布在系统的各处的时候,这种蔓延现象实际上说明了系统创建职责分配的混乱,缺少一个进行拥有创建知识的信息专家(请注意这里的表述)。 创建逻辑通常是这样的,它包含了一系列if-else的判断逻辑,根据运行时的具体参数来决定对象的创建。如果这部分是确定的那么我们也不必过多的考虑它。但是如果它是变化的,比如删减一个对象的创建或者增加一个新类型的创建,那么这部分代码是要被经常修改的,这种修改实际上说明我们已经违反了OCP原则(关闭修改,打开扩展),那么根据识别变化封装变化的原则我们必须把这一部分进行抽取并进行隔离。

  翻看所有设计模式相关的书籍我们都可以看到这样的表述:

  工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以在运行时动态决定将哪一个类实例化。

  看样子工厂模式正是我们需要的,但我们并不急于下手,看看是不是另有蹊径,[接口]怎么样?《Java与模式》一书就是给出了这样一个接口实现的方式。

  我习惯把接口理解成契约和行为,创建出来不同的对象,对象的区别实际上行为的差别。接口是不是可以?假设我么使用了接口,问题解决了么?没有!增加新类时同样面临修改代码的问题。这个方法只是转化了问题的形式,并没有真正解决问题,使用接口我们失去的代码复用的优势,而大量的具体类上使用接口不是什么好主意,虽然《Java与模式》一书全部使用接口实现。如果要创建的对象没有共同的业务逻辑那么可以使用一个接口来扮演抽象产品的角色,但是更多的情况是具体产品之间是存在共有的业务逻辑,那么这些逻辑就应该移到抽象角色里面。

  其实我们就是将创建知识集中并设立一个信息专家专门负责对象的创建。简单工厂模式是我们的第一个拥有创建知识的信息专家:

  简单工厂

  我们考虑最简单的抽取和隔离方法就是使用[  简单工厂  ]。简单工厂的特点就是参数化创建对象,简单工厂必须知道每一种产品以及何时提供给Client。有人会说简单工厂还是换汤不换药,添加新类的时候还是需要修改这部分的代码!诚然,那么我们获得了什么好处呢?集中变化! 这很好的符合了DRY原则(Don't Repeat Yourself!)创建逻辑存放在单一的位置,即使它变化,我们也只需要修改一处就可以了。DRY 很简单,但却是确保我们代码容易维护和复用的关键。DRY原则同时还提醒我们:对系统职能进行良好的分割!职责清晰的界限一定程度上保证了代码的单一性。这句话对我们后续的分析极具指导意义,毕竟简单工厂只是低层次上的代码复用。

  题外话:简单工厂的确简单但是其背后的DRY原则在实践中让我们受益匪浅,去年我和我的搭档做站点的升级工作,写了很多重复的代码;代码重复,源代码组织混乱,没有做好规划和职责分析是原罪。今年新项目,DRY原则是我头顶的达摩克利斯之剑,不做重复的事情成为我进行项目计划组织管理的重要标准。

  关于简单工厂模式的阶段总结:

  识别变化隔离变化,简单工厂是一个显而易见的实现方式
  简单工厂将创建知识集中在单一位置符合了DRY
  客户端无须了解对象的创建过程,某种程度上支持了OCP
  添加新的产品会造成创建代码的修改,这说明简单工厂模式对OCP支持不够
  简单工厂类集中了所有的实例创建逻辑很容易违反高内聚的责任分配原则。
  Factory Method模式

  简单工厂模式之所以对OCP支持不够,就是因为它拥有了太多的知识:有多少种产品以及创建产品的时机。或者说,简单工厂承担了太多的职责。DRY原则提示我们要清晰的划清对象职责的界限。一个方法就是权力下放,将创建的知识移交给子类。知识的递交意味着职责的转移。

  这样做之后,我们重新审视类之间的关系:核心工厂类不再负责所有产品的创建,核心类的层次上升成为一个抽象工厂角色,仅仅负责给出具体子类必须实现的接口,而不关系具体产品的创建细节。创建的知识由具体工厂拥有。而这时系统内也出现了一个平行的等级结构,产品家族的等级结构以及对应的工厂等级结构。

  简单工厂把核心放在一个具体类上。Factory Method模式把核心放在抽象类,具体工厂类继承了创建行为。具体工厂都拥有相同的接口所以还有一个别名叫多态工厂模式。这是我们关注点已经从实现转移到了“接口”:关注动机而非实现,是基本的OO设计原则,将实现隐藏在接口之后实际上是将对象的实现与它们的对象解耦了。从“依赖”的角度,系统中依赖的已经不再是一个个具体的实现,而是一个抽象。这就是DIP原则:高层模块不应该依赖低层模块,两者都应该依赖于抽象。这个原则隐含的意思是:对象之间只在概念层次存在耦合,在实现层次不能耦合!

  工厂方法模式的应用需要完全遵守里氏替换原则为前提。即父类出现的地方能够替换成子类,工厂方法模式的应用才能成为可能。

  我们要添加一个新的产品,只要添加这个产品类和它的工厂类就可以了。没有必要修改Client和已经存在的工厂代码。Factory Method完全支持OCP原则。

  抽象工厂模式

  抽象工厂向客户端提供了一个接口,使得客户端在不指定具体产品类型的时候就可以创建产品族中的产品对象。这就是抽象工厂的用意。抽象工厂面的问题是多个等级产品等级结构的系统设计。抽象工厂和工厂方法模式最大的区别就在于后者只是针对一个产品等级结构;而抽象工厂则是面对多个等级结构。

  同样出色的完成了把应用程序从特定的实现中解耦,工厂方法使用的方法是继承,而抽象工厂使用的对象组合。抽象工厂提供的是一个产品家族的抽象类型,这个类型的子类完成了产品的创建。

  我们在工厂方法模式中提到的OCP DIP LSP等原则的表述也适用于抽象工厂模式.

  我曾经在《视角的力量--再说OO设计原则》一文中提到抽象出来高层策略是需要有一定稳定性的。抽象工厂作为一个高层抽象如果它的接口发生变化,那么影响是巨大的:所有的子类都要进行修改!这就要求抽象工厂的接口设计是高度抽象的!

  总结:

  发现变化隔离封装变化是动因,关闭修改打开扩展是限制
  简单工厂很好地遵守了DRY原则,对OCP原则支持不足
  工厂方法模式完全支持了OCP原则,使用的机制是继承
  抽象工厂模式 工厂方法模式都完全支持OCP原则
  LSP原则是OCP成为可能的重要原则,抽象工厂模式、工厂方法模式完全遵守LSP
  依赖于抽象,一个类派生自具体类明显违背了DIP原则
  GRASP是另外一个设计模式体系,它与GOF设计模式在很多地方是殊途同归,了解一下GRASP可以帮助我们思考
原文连接:http://www.cnblogs.com/me-sa/archive/2008/05/06/factoryoop.html

分享到:
评论

相关推荐

    剖析设计模式与设计原则

    总之,设计模式和设计原则是软件工程的重要组成部分,它们提供了可复用的解决方案和指导方针,帮助我们在面对复杂问题时做出明智的选择。通过深入研究“OO Principles Explained译文.pdf”,我们可以进一步巩固这些...

    23种设计模式,OO思想

    标题和描述中提到的“23种设计模式,OO思想”,是软件工程领域的一个核心概念,尤其是对于面向对象编程(Object-Oriented Programming,简称OO)的深入理解和实践至关重要。设计模式是由Erich Gamma、Richard Helm、...

    OO设计五个原则.pdf

    《OO设计五个原则》深入探讨了面向对象设计(Object-Oriented Design,简称OO设计)中的五大核心原则,这些原则是软件工程领域公认的基石,旨在提高软件系统的稳定性、可维护性和可扩展性。本文将详细解析这五大原则...

    面向对象设计原则和设计模式的概念

    面向对象设计原则与设计模式是软件工程领域的重要组成部分,它们为构建高质量、可维护和可扩展的软件系统提供了指导方针。下面将详细阐述面向对象设计原则及其如何促进软件的复用,以及设计模式的概念。 ### 面向...

    设计模式入门指导

    在探讨设计模式的入门知识之前,我们需要对面向对象(Object-Oriented,OO)和面向过程(Procedure-Oriented)的编程思想有所了解。面向过程的编程是以事件为中心的,注重于具体的操作步骤,如C语言就是面向过程编程...

    函数式编程中的设计模式.pdf

    FP的设计原则与OO的设计原则S.O.L.I.D有显著区别: 1. 引用透明,无副作用(referential transparency):这意味着同样的输入总会得到同样的输出,函数在执行中不会产生外部可观察的状态变化。 2. 不可变性...

    面向对象的思想与设计模式

    2. 工厂方法模式:与简单工厂模式相比,工厂方法模式将对象创建的职责委托给子类,每种产品类型都有一个对应的工厂类负责创建。这样增加了系统的灵活性,当需要添加新产品时,只需创建新的工厂类即可,符合开闭原则...

    java设计模式之面向对象的思想(think in OO(Object Oriented))

    1. 工厂模式(Factory Pattern):工厂模式是一种创建型设计模式,它提供了一个创建对象的接口,但让子类决定实例化哪一个类。这将类的实例化过程延迟到子类进行,增强了程序的可扩展性。 2. 单例模式(Singleton ...

    《设计模式--基于C#的工程化实现及扩展》.(王翔).rar.rar

    本书涵盖了各种经典的设计模式,包括创建型模式(如单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式)、结构型模式(如适配器模式、桥接模式、装饰模式、组合模式、外观模式、代理模式、享元模式)以及行为...

    c#代码介绍23种设计模式-02简单工厂模式(附代码)

    在设计模式中,简单工厂模式我们也可以理解为负责生产对象的一个类。 我们平常编程中,当使用"new"关键字创建一个对象时,此时该类就依赖与这个对象,也就是他们之间的耦合度高, 当需求变化时,我们就不得不去修改...

    软件工程概述及设计模式ppt课件.ppt

    软件工程概述及设计模式ppt课件 本篇ppt课件主要介绍了软件工程的概述和设计模式的相关知识。下面是从ppt课件中提取的相关知识点: 软件工程概述 软件工程是指通过工程化方法来开发、维护和更新软件的技术和管理...

    兰新EIC管理模式——二OO四年经济运营原则及考核、标体系.doc

    3. 定价原则:产品、工程和服务的价格由顾客决定,基于市场动态建立价格平台。产品最终售价要考虑多种因素,如买断价、卖出服务价、费用、税金和利润等,并需经过授权审批。 4. 内部优先原则:在相同条件下,集团...

    Head.First设计模式_PDF.part1

    Head.First设计模式_PDF(高清扫描版) 第一部分(共三部分) 在我的资源下可找到其他两部部分 强大的写作阵容。《Head First设计模式》作者Eric Free...13 与设计模式相处:真实世界中的模式 A 附录A:剩下的模式

    Head_First_设计模式

    每一章均会引入一至多个设计模式,并结合相关的OO原则进行讲解,帮助读者理解模式背后的逻辑与目的。作者指出,当面临设计抉择时,应回归OO原则,以此作为决策依据,从而达到更好的设计效果。 ### 教学方法与内容...

    面向对象的设计原则 doc

    通过以上六个面向对象设计原则的学习与实践,可以显著提高软件的质量和可维护性,同时也能更好地应对不断变化的需求。这些原则并非孤立存在,而是相互关联、相辅相成的。在实际开发过程中,应根据项目的具体情况灵活...

    12种常用设计模式C#代码示例

    设计原则(OO原则)汇总 1、封装变化:找出应用中可能变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。 2、针对接口编程,而不是针对实现编程。 3、多用组合,少用继承。 4、为了交互对象之间的送...

    第七讲-面向对象程序的需求分析与设计原则v4.01

    面向对象程序的需求分析与设计原则是软件开发中的关键步骤,特别是在OO(面向对象)编程范式下。这一讲主要探讨如何有效地进行面向对象程序的需求分析,以及遵循的设计原则,以确保软件的质量、可维护性和扩展性。 ...

    Head.First 设计模式学习笔记.pdf

    设计模式是在软件工程实践中总结出来的经典解决方案,它们可以帮助开发者构建更加健壮、可维护的软件系统。通过学习《Head First 设计模式》,开发者可以深入了解各种设计模式的应用场景、优缺点以及实现方式。上述...

    软件工程PDF课件 08_OODesign面向对象设计.pdf

    面向对象设计是软件工程中的核心...总结起来,面向对象设计是软件工程中的关键步骤,它遵循模块化、内聚、耦合和复用等原则,通过系统设计、对象设计、数据库设计和用户界面设计等环节,创建出高效、可维护的软件系统。

Global site tag (gtag.js) - Google Analytics