简单工厂模式
定义
简单工厂模式(Simple Factory Pattern)是值一个工厂对象觉得创建出哪一种产品类的实例。
属于创建型模式,但是它不属于GOF 23种设计模式。
简单工厂使用于工厂类负责创建的对象较少的场景,并且客户端值需要传入工厂类的参数,对于如何创建对象的逻辑不需要关系。
代码示例
我们以我们生活中常见的小汽车为例,小汽车有宝马、奔驰、玛萨拉蒂等等品牌,那么我么可以定义一个小汽车的标准接口ICar:
public interface ICar {// 生产汽车void create();}
创建一个宝马汽车的示例BMW:
public class BMW implements ICar {@Overridepublic void create() {System.out.println("======生产宝马汽车======");}}
客户端在调用的时候,我们一般是这样写的:
public static void main(String[] args) {ICar car = new BMW();car.create();}
上面代码中,父类ICar指向了子类BMW的引用。一般我们这样写没什么问题,但是如果在业务需要扩展,需要创建更多的品牌的汽车时,那么我们的客户端依赖会变得越来越臃肿,要减弱客户端的依赖,那我们就需要将创建细节隐藏,使用一个简单工厂类来优化我们的代码。
public class CarFactory {public ICar create(String name) {if ("BMW".equals(name)) {return new BMW();} else if ("benz".equals(name)) {return new Benz();}return null;}}
修改客户端调用代码:
public class SimpleFactoryTest {public static void main(String[] args) {CarFactory carFactory = new CarFactory();ICar car = carFactory.create("BMW");car.create();}}
客户端调用是简单了,但是我们的工厂类违反了开闭原则,因为在有新的汽车要生产时,我们需要修改 CarFactory 中的 create 方法。我们可以用反射技术,来对工厂类进行优化:
public class CarFactory {public ICar create(Class clazz) {try {if (clazz != null) {return (ICar) clazz.newInstance();}}catch (Exception e){e.printStackTrace();}return null;}}
这时候,我们调用时只需要传入 Class 对象即可,这样既避免了在客户端调用时传错参数,也可以避免工厂类的修改。
工厂方法模式
定义
工厂方法模式(Fatory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
工厂方法模式主要解决产品扩展的问题,在简单工厂中,随着产品链的丰富,如果每个汽车的创建逻辑有区别的话,工厂的职责会变得越来越多,有点像万能工厂,并不便于维护。根据单一职责原则我们将职能继续拆分,专人干专事。 宝马汽车有宝马工厂创建,奔驰汽车由奔驰工厂创建,这样无论汽车的生产有怎样特殊的需求,都不影响其他汽车的生产。
代码示例
我们先对工厂做一个顶层抽象:
public interface ICarFactory {ICar create();}
在分别创建子工厂,BMWFactory和BenzFactory:
public class BMWFactory implements ICarFactory {@Overridepublic ICar create() {return new BMW();}}
public class BenzFactory implements ICarFactory {@Overridepublic ICar create() {return new Benz();}}
客户端调用如下:
public class FactoryMethodTest {public static void main(String[] args) {ICarFactory factory = new BMWFactory();ICar bmw = factory.create();bmw.create();ICarFactory factory2 = new BenzFactory();ICar benz = factory2.create();benz.create();}}
使用场景
工厂方法使用于以下场景:
- 创建对象需要大量的重复代码
- 客户端不依赖于产品类实例如何被创建、实现等细节
-
缺点
虽然工厂方法简单,清晰,但是当需要创建的产品过多时会导致类爆炸。要解决类爆炸的问题,就需要用到抽象工厂模式。
抽象工厂模式
定义
抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
在讲解抽象工厂模式之前,我们需要先了解两个概念:产品族和产品等级结构。
产品族:所谓的产品族即是同一个厂家生产的多个产品。
产品等级结构:产品等级结构即有多个厂家可以生成相同的产品。
比如工厂A能够生产 A、B、C三种产品,工厂B也能生产A、B、C三种产品,那么A、B、C就表示一个产品族,工厂A 生产 A 和工厂B生产的A就表示一个产品等级结构。代码示例
我们还是以汽车为例,一个汽车的组成是有发动机、车身、变速箱等等部件组成。我们先来创建一个ICarFactory的工厂接口:
public interface ICarFactory {ICarBody createBody();IEngine createEngine();IGearbox createGearbox();}
然后创建需要使用到的产品接口
public interface ICarBody {void create();}
public interface IEngine {void create();}
```java public interface IGearbox { void create(); }
这些产品的实现:```javapublic class BMWBody implements ICarBody {@Overridepublic void create() {System.out.println("生产bmw车身");}}
public class BMWEngine implements IEngine {@Overridepublic void create() {System.out.println("生产bmw 引擎");}}
public class BMWGearbox implements IGearbox {@Overridepublic void create() {System.out.println("生产bmw变速箱");}}
产品族工厂:
public class BmwFactory implements ICarFactory {@Overridepublic ICarBody createBody() {return new BMWBody();}@Overridepublic IEngine createEngine() {return new BMWEngine();}@Overridepublic IGearbox createGearbox() {return new BMWGearbox();}}
测试:
public class AbstractFactoryTest {public static void main(String[] args) {ICarFactory carFactory = new BmwFactory();carFactory.createBody().create();carFactory.createEngine().create();carFactory.createGearbox().create();}}
缺点
抽象工厂虽然能一定程度上解决类爆炸的问题,但是很显然它不符合开闭原则。这是因为我们在产品族中加入一个产品时,从抽象工厂到具体实现都需要修改。因此抽象工厂也是优缺点点。
1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口 。
2、增加了系统的抽象性和理解难度 。
