很多时候我们只是期望获取对象实例即可,并不关心实例构造过程(例如相关Field的具体如何设置)。这个时候就可以将通过工厂模式来解决这个问题,其同样也是一种创建型模式。将实例的具体构造过程进行封装以对外屏蔽,就像现实世界中我们只需从工厂直接拿取产品即可,而无需care产品在工厂里的具体制造过程
假设有三种品牌的汽车:BMW宝马、Benz奔驰、Rolls Royce劳斯莱斯。客户订购了其中某一品牌的汽车,那么只需要在汽车工厂把车造好了直接去取就好了,至于车咋造的,相信没有客户会Care吧……实际上在软件工程领域中,这样的需求也经常出现,Client只是需要一个实例对象而已,至于这个对象具体怎么构造的,他不需要也不想知道这么多细节。这个时候就可以借用工厂的概念来解决这个问题,只不过这里的工厂不造车罢了,改为创建实例
这里,我们先来介绍 Simple Factory Pattern 简单工厂模式。其有以下三种角色:
现在,就让我们来通过代码实现 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();
}
}
从测试结果可以看出,结果符合预期
前文介绍的Simple Facotry Pattern 简单工厂模式,虽然可以让client不用再关注实例的具体构造过程了,但是其存在一个明显的缺点。每当我们需要添加一个新的Car实现类时,都需要对CarFactory类进行修改。这显然破坏了开闭原则,即对扩展开放、对修改关闭。那如何解决这个问题呢?这个时候就需要引入本文的正题了——Factory Patttern 工厂模式,其又被称作工厂方法模式。该设计模式与简单工厂模式区别、改进之处就在于,其对于工厂的设计是基于接口的思想,具体地,其将简单工厂模式中的工厂角色改进为以下两个角色
显然该设计模式下的抽象产品角色、具体产品角色没有发生变化,所以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();
}
}
可以看到测试结果,符合预期