03.Factory Pattern 工厂模式

很多时候我们只是期望获取对象实例即可,并不关心实例构造过程(例如相关Field的具体如何设置)。这个时候就可以将通过工厂模式来解决这个问题,其同样也是一种创建型模式。将实例的具体构造过程进行封装以对外屏蔽,就像现实世界中我们只需从工厂直接拿取产品即可,而无需care产品在工厂里的具体制造过程

03.Factory Pattern 工厂模式_第1张图片

Simple Factory Pattern 简单工厂模式

假设有三种品牌的汽车:BMW宝马、Benz奔驰、Rolls Royce劳斯莱斯。客户订购了其中某一品牌的汽车,那么只需要在汽车工厂把车造好了直接去取就好了,至于车咋造的,相信没有客户会Care吧……实际上在软件工程领域中,这样的需求也经常出现,Client只是需要一个实例对象而已,至于这个对象具体怎么构造的,他不需要也不想知道这么多细节。这个时候就可以借用工厂的概念来解决这个问题,只不过这里的工厂不造车罢了,改为创建实例

这里,我们先来介绍 Simple Factory Pattern 简单工厂模式。其有以下三种角色:

  1. 抽象产品角色:其定义了具体产品的实现类所具有的共有方法,一般通过接口实现。本文中其就是Car接口,其定义了汽车所具备的功能
  2. 具体产品角色:其是抽象产品角色的具体实现类,即是客户真正需要的产品。在这里,即为Benz、BMW、RollsRoyce类
  3. 工厂角色:其是一个工厂类。通过一个静态方法来获取该工厂所构建的对象实例,故简单工厂模式又被称作静态工厂方法模式。具体地,可通过参数来指定所需的具体品牌的汽车

现在,就让我们来通过代码实现 Simple Factory Pattern 简单工厂模式。第一步,先定义一个汽车的接口

/**
 * 抽象产品角色: 车
 */
public interface Car {	
    void drive();
}

然后再提供汽车接口的具体实现类

/**
 * 具体产品角色:奔驰 Benz
 */
public class Benz implements Car {
    @Override
    public void drive() {
        System.out.println("司机在驾驶Benz");
    }
}
...
/**
 * 具体产品角色:宝马 BMW
 */
public class BMW implements Car {
    @Override
    public void drive() {
        System.out.println("司机在驾驶BMW");
    }
}
...
/**
 * 具体产品角色:劳斯莱斯 Rolls Royce
 */
public class RollsRoyce implements Car {
    @Override
    public void drive() {
        System.out.println("司机在驾驶Rolls Royce");
    }
}

最后,通过一个CarFactory工厂实现实例的构造、获取

/**
 * 工厂角色
 */
public class CarFactory {
    public static Car getCar(String type) {
        if( type==null ) {
            return null;
        }
        Car car = null;
        switch (type) {
            case "BMW":
                car = new BMW();
                break;
            case "Benz":
                car = new Benz();
                break;
            case "RollsRoyce":
                car = new RollsRoyce();
                break;
            default:
                car = null;
        }
        return car;
    }
}

下面通过一个测试用例来演示其使用方式

public class SimpleFactoryDemo {
    public static void main(String[] args) {
        Car bmw = CarFactory.getCar("BMW");
        bmw.drive();

        Car benz = CarFactory.getCar("Benz");
        benz.drive();

        Car rollsRoyce = CarFactory.getCar("RollsRoyce");
        rollsRoyce.drive();
    }
}

从测试结果可以看出,结果符合预期

03.Factory Pattern 工厂模式_第2张图片

Factory Pattern 工厂模式

前文介绍的Simple Facotry Pattern 简单工厂模式,虽然可以让client不用再关注实例的具体构造过程了,但是其存在一个明显的缺点。每当我们需要添加一个新的Car实现类时,都需要对CarFactory类进行修改。这显然破坏了开闭原则,即对扩展开放、对修改关闭。那如何解决这个问题呢?这个时候就需要引入本文的正题了——Factory Patttern 工厂模式,其又被称作工厂方法模式。该设计模式与简单工厂模式区别、改进之处就在于,其对于工厂的设计是基于接口的思想,具体地,其将简单工厂模式中的工厂角色改进为以下两个角色

  1. 抽象工厂角色:其定义了不同具体产品各自工厂的通用接口
  2. 具体工厂角色:其是抽象工厂的具体实现类,一个具体的工厂类只负责生产某一种产品。这样以后如果需要新的产品,只需添加一个该产品的工厂类即可,而不需要修改之前的代码

显然该设计模式下的抽象产品角色、具体产品角色没有发生变化,所以Car接口及其具体实现类的Benz、BMW、RollsRoyce部分无需改动,如下所示

/**
 * 抽象产品角色: 汽车
 */
public interface Car {
    void drive();
}
...
/**
 * 具体产品角色:奔驰 Benz
 */
public class Benz implements Car {
    @Override
    public void drive() {
        System.out.println("司机在驾驶Benz");
    }
}
...
/**
 * 具体产品角色:宝马 BMW
 */
public class BMW implements Car {
    @Override
    public void drive() {
        System.out.println("司机在驾驶BMW");
    }
}
...
/**
 * 具体产品角色:劳斯莱斯 Rolls Royce
 */
public class RollsRoyce implements Car {
    @Override
    public void drive() {
        System.out.println("司机在驾驶Rolls Royce");
    }
}

现在,我们先来定义一个汽车工厂的接口

/**
 * 抽象工厂角色:汽车工厂
 */
public interface CarFactory {
    Car getCar();
}

然后,针对三种不同的产品Benz、BMW、RollsRoyce,分别提供各自具体的工厂类

/**
 * 具体工厂角色:Benz 工厂
 */
public class BenzFactory implements CarFactory{
    @Override
    public Benz getCar() {
        return new Benz();
    }
}
...
/**
 * 具体工厂角色:BMW 工厂
 */
public class BMWFactory implements CarFactory{
    @Override
    public BMW getCar() {
        return new BMW();
    }
}
...
/**
 * 具体工厂角色:Rolls Royce 工厂
 */
public class RollsRoyceFactory implements CarFactory{
    @Override
    public RollsRoyce getCar() {
        return new RollsRoyce();
    }
}

现在让我们来实际测试下

public class FactoryMethodDemo {
    public static void main(String[] args) {
        CarFactory factory = new BenzFactory();
        Car benz = factory.getCar();
        benz.drive();

        factory = new BMWFactory();
        Car bmw = factory.getCar();
        bmw.drive();

        factory = new RollsRoyceFactory();
        Car rollsRoyce = factory.getCar();
        rollsRoyce.drive();
    }
}

可以看到测试结果,符合预期

03.Factory Pattern 工厂模式_第3张图片

参考文献

  1. Head First 设计模式 弗里曼著

你可能感兴趣的:(设计模式,java,设计模式)