模式(FactoryMethod)的定义:
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。满足创建型模式中所要求的“创建与使用相分离”的特点。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”。
模式的3种变体:
• 简单工厂模式: 允许接口创建对象,但不会暴露对象的创建逻辑。
• 工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则是交由子类决定的。
• 抽象工厂模式:抽象工厂是一个能够创建一系列相关的对象而无需指定/公开其具体类的接口。该模式能够提供其他工厂的对象,在其内部创建其他对象。
一、简单工厂模式:
1.1定义
简单工厂模式又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。 其UML类图如下:
1.2类图
1.3简单工厂模式代码
简单工厂类:
客户端代码:
1.4简单工厂模式的优缺点
优点:
• 简单工厂包含必要的判断逻辑,简单工厂实现了对象的创建和使用的分离。
• 客户端无需知道所创建的具体产品类的类名,只需要具体产品类对应的参数即可。
• 在不修改任何客户端代码的情况下更换和增加新的具体产品类一定程度上提高了系统的灵活性。
缺点:
• 工厂类的职责过重,例如算术运算中简单工厂中包含加减乘除的逻辑判断语句,一旦它出现有问题,整个系统都会出问题。
• 在添加新的类的时候,例如添加开根号运算那么简单工厂类就要修改,违反了开放—封闭原则不利于系统的扩展和维护。
• 简单工厂的静态方法,使得工厂角色无法形成基于继承的等级结构。
二、工厂方法模式:
2.1定义
工厂方法模式是对简单工厂模式进一步的解耦,因为在工厂方法模式中是一个子类对应一个工厂类,而这些工厂类都实现于一个抽象接口。工厂方法模式是一个用于创建对象的接口,让子类决定实例化哪一个类。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
2.2类图
2.3工厂模式代码
定义一个工厂接口:
定义具体工厂类:
客户端代码:
工厂方法克服了简单工厂的缺点,增加新的产品时,不必修改现存的代码只需要增加新代码即可,满足开放封闭原则。
2.3工厂方法的优缺点
优点:
• 原来是自己创建对象(new),而现在可以直接通过工厂传递所需要的对象。
• 使用工厂模式易于功能扩展,只需返回共有的父类对象(此对象是多态对象),而不对其他造成影响。
• 遵循代码开闭原则。
• 封装性:对外只保留基类(所有产线共有特征类),具体实现交由工厂选择。
缺点:
假如某个具体产品类 需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改会变得特别麻烦。例如:每增加一个产品,相应的也要增加一个子工厂,会加大了额外的开发量。
三、抽象工厂模式(Abstract Factory Pattern) :
3.1定义
抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
3.2类图
抽象工厂模式包含如下角色:
• 抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心。
• 具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。
• 抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
• 具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西。
3.3抽象工厂模式代码
示例:
例如:Q3和Q7有不同的轮胎、发动机、制动系统。虽然生产的零件不同,型号不同。但是根本上都有共同的约束,就是轮胎、发动机、制动系统。设计如下:
1.需要一个抽象工厂,里面有三个接口分别为生产轮胎、发动机、制动系统,抽象类
2.需要三个抽象产品分别为轮胎、发动机、制动系统
3.需要实现上面的三个抽象类,定义出每个类不同的对象,比如:普通轮胎和越野轮胎
4.需要两个具体类继承自上面的抽象类,实现具体的工厂,比如:生产Q3的工厂A和生产Q7的工厂B
5.在客户端new出对应的具体工厂并调用对应的生产方法
1.抽象工厂:
2.根据抽象接口定义不同的对象:
3.实现具体的工厂类:
4.客户端使用:
5.结果输出:
3.4抽象工厂模式的优缺点
抽象工厂模式的优点:
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
抽象工厂模式的缺点:
产品族的扩展费力,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
3.5抽象工厂模式与工厂方法模式的区别
• 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于:工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
• 在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。我们依然拿生产汽车的例子来说明他们之间的区别。