设计模式工厂模式

工厂顾名思义就是创建产品,本质就是用工厂方法代替new操作创建一种实例化对象的方式。根据不同的实现方式和抽象级别又可分为简单工厂,工厂方法和抽象工厂三种模式。

案例


需求

封装一个SqlHelper类,实现对SqlServer的操作,且后续可能需要同时支持SqlServer,MySql,Oracle等主流数据库。

这是我们平常非常熟悉的需求了,根据需求我们可以得到如下类图:

简单工厂


UML类图

我们将前面SqlHelper例子中的类图进行一次抽象,就得到更通用的简单工厂模式类图了。其中对应关系如下:

  • Client:SqlHelper
  • SimpleFactory:DbConnectionFactory
  • AbstractProduct:DbConnection
  • Product1、Product2:SqlConnection、MySqlConnection

定义

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。由于简单工厂通常会使用静态方法实现,因此也叫做静态工厂模式,它不属于23种GOF设计模式之一。

优缺点

  • 优点
    • 实现了对责任的分割,隔离了变化,因为它提供了专门的工厂类用于创建对象。
    • 通过配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
  • 缺点
    • 集中了所有实例的创建逻辑,违反了单一职责原则
    • 扩展困难,一旦添加新产品就不得不修改工厂逻辑,违反了开闭原则

工厂方法


案例改进

由于简单工厂模式不满足开闭原则,因此,我们需要对其进行改进,将简单工厂进行一次抽象,然后让每个具体的工厂子类负责生产对应的产品,具体改进如下:

UML类图

同样的,我们进行一次抽象,就得到工厂方法模式的类图了。

定义

定义一个工厂父类,工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。即将类的实例化延迟到工厂类的子类中完成,即由子类来决定应该实例化哪一个类。

优缺点

  • 优点: 满足各种设计原则
  • 缺点:类的个数成倍增加,增加了系统的复杂度

抽象工厂


需求扩展(参数化查询)

当然,我们知道,工作中,更通用SqlHelper没有这么简单,比如,我们至少需要参数化查询,防止用户的SQL脚本注入攻击。根据工厂方法模式的思路进一步改进,如下图所示:

不难发现,随着需求的增加,会出现如下问题:

  • 类的数量成倍增长
  • 无法保证类之间的依赖关系

改进

基于这些问题,我们继续改进,将多个相互关联的工厂(DbConnect和DbParameter使用时通常有密切联系)合并,得到如下类图:

UML类图

总结出更抽象的类图如下:

定义

抽象工厂是工厂方法的升级版,为相关或者相互依赖的对象提供一个统一的接口,而且无需指定他们的具体实现类。

优缺点

  • 优点

    • 对产品族进行约束,封装性好
  • 缺点

    • 产品族扩展困难,添加一个产品需要修改抽象和具体工厂类,违背开闭原则。

总结

简单工厂模式由于违背了众多设计原则,因此,很多时候会被视为是一种反模式而不是设计模式,但是由于面向对象设计语言中反射机制的存在,使得简单工厂模式使用的反而最为广泛;

工厂方法虽然时最满足设计原则的,但是由于它会使系统变得过于复杂,因此,反而用的最少;

抽象工厂模式更多体现的对产品族的约束,同时,相对于工厂方法模式,也降低了系统的复杂度,极端情况下,如果抽象工厂模式中的产品族只有一个产品,那么抽象工厂模式也就退化成了工厂方法模式。因此,很多人说抽象工厂模式是工厂的工厂,此观点是值得商榷的。

源码链接

原文地址:https://www.cnblogs.com/FindTheWay/p/13559211.html