很多时候我们只是期望获取对象实例即可,并不关心实例构造过程(例如相关Field的具体如何设置)。这个时候就可以将通过工厂模式来解决这个问题,其同样也是一种创建型模式。将实例的具体构造过程进行封装以对外屏蔽,就像现实世界中我们只需从工厂直接拿取产品即可,而无需care产品在工厂里的具体制造过程
Simple Factory Pattern 简单工厂模式
假设有三种品牌的汽车:BMW宝马、Benz奔驰、Rolls Royce劳斯莱斯。客户订购了其中某一品牌的汽车,那么只需要在汽车工厂把车造好了直接去取就好了,至于车咋造的,相信没有客户会Care吧……实际上在软件工程领域中,这样的需求也经常出现,Client只是需要一个实例对象而已,至于这个对象具体怎么构造的,他不需要也不想知道这么多细节。这个时候就可以借用工厂的概念来解决这个问题,只不过这里的工厂不造车罢了,改为创建实例
这里,我们先来介绍 Simple Factory Pattern 简单工厂模式。其有以下三种角色:
- 抽象产品角色:其定义了具体产品的实现类所具有的共有方法,一般通过接口实现。本文中其就是Car接口,其定义了汽车所具备的功能
- 具体产品角色:其是抽象产品角色的具体实现类,即是客户真正需要的产品。在这里,即为Benz、BMW、RollsRoyce类
- 工厂角色:其是一个工厂类。通过一个静态方法来获取该工厂所构建的对象实例,故简单工厂模式又被称作静态工厂方法模式。具体地,可通过参数来指定所需的具体品牌的汽车
现在,就让我们来通过代码实现 Simple Factory Pattern 简单工厂模式。第一步,先定义一个汽车的接口
1 2 3 4 5 6
|
public interface Car { void drive(); }
|
然后再提供汽车接口的具体实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public class Benz implements Car { @Override public void drive() { System.out.println("司机在驾驶Benz"); } } ...
public class BMW implements Car { @Override public void drive() { System.out.println("司机在驾驶BMW"); } } ...
public class RollsRoyce implements Car { @Override public void drive() { System.out.println("司机在驾驶Rolls Royce"); } }
|
最后,通过一个CarFactory工厂实现实例的构造、获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
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; } }
|
下面通过一个测试用例来演示其使用方式
1 2 3 4 5 6 7 8 9 10 11 12
| 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(); } }
|
从测试结果可以看出,结果符合预期
Factory Pattern 工厂模式
前文介绍的Simple Facotry Pattern 简单工厂模式,虽然可以让client不用再关注实例的具体构造过程了,但是其存在一个明显的缺点。每当我们需要添加一个新的Car实现类时,都需要对CarFactory类进行修改。这显然破坏了开闭原则,即对扩展开放、对修改关闭。那如何解决这个问题呢?这个时候就需要引入本文的正题了——Factory Patttern 工厂模式,其又被称作工厂方法模式。该设计模式与简单工厂模式区别、改进之处就在于,其对于工厂的设计是基于接口的思想,具体地,其将简单工厂模式中的工厂角色改进为以下两个角色
- 抽象工厂角色:其定义了不同具体产品各自工厂的通用接口
- 具体工厂角色:其是抽象工厂的具体实现类,一个具体的工厂类只负责生产某一种产品。这样以后如果需要新的产品,只需添加一个该产品的工厂类即可,而不需要修改之前的代码
显然该设计模式下的抽象产品角色、具体产品角色没有发生变化,所以Car接口及其具体实现类的Benz、BMW、RollsRoyce部分无需改动,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
public interface Car { void drive(); } ...
public class Benz implements Car { @Override public void drive() { System.out.println("司机在驾驶Benz"); } } ...
public class BMW implements Car { @Override public void drive() { System.out.println("司机在驾驶BMW"); } } ...
public class RollsRoyce implements Car { @Override public void drive() { System.out.println("司机在驾驶Rolls Royce"); } }
|
现在,我们先来定义一个汽车工厂的接口
1 2 3 4 5 6
|
public interface CarFactory { Car getCar(); }
|
然后,针对三种不同的产品Benz、BMW、RollsRoyce,分别提供各自具体的工厂类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public class BenzFactory implements CarFactory{ @Override public Benz getCar() { return new Benz(); } } ...
public class BMWFactory implements CarFactory{ @Override public BMW getCar() { return new BMW(); } } ...
public class RollsRoyceFactory implements CarFactory{ @Override public RollsRoyce getCar() { return new RollsRoyce(); } }
|
现在让我们来实际测试下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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(); } }
|
可以看到测试结果,符合预期
参考文献
- Head First 设计模式 弗里曼著