工厂模式(Factory Pattern)属于创建型模式。
在工厂模式中,创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
如果需要创建一个对象,最简单的方式就是直接 new 一个。而工厂模式代替了传统的直接 new 的形式,那么为什么要替代呢?如果所有的对象都通过 new 的方式去创建,那么当程序中大量使用此对象时,突然有一天这个对象的构造方法或是类名发生了修改,那就得逐个去进行修改。
根据迪米特法则,应该尽可能地少与其他类进行交互,所以可以将那些需要频繁出现的对象创建,封装到一个工厂类中。当需要对象时,直接调用工厂类中的工厂方法来生成对象,这样,就算类出现了变动,只需要修改工厂中的代码即可,而不是大面积地进行修改。同时,可能某些对象的创建并不只是一个 new 就可以搞定,可能还需要更多的步骤来准备构造方法需要的参数。
以汽车工厂生产汽车为例介绍简单工厂模式
1.定义汽车(接口)
- public interface Car {
- void name();
- }
2.定义BMW类
- public class BMW implements Car{
- @Override
- public void name() {
- System.out.println("宝马");
- }
- }
3.定义Audi类
- public class Audi implements Car{
- @Override
- public void name() {
- System.out.println("奥迪");
- }
- }
4.定义汽车工厂
- //简单工厂模式(静态工厂模式)
- //增加一个新产品,如果不修改代码做不到
-
- //开发封闭原则
- public class CarFactory {
- //方法一
- public static Car getCar(String car){
- if(car.equals("宝马")){
- return new BMW();
- }else if (car.equals("奥迪")){
- return new Audi();
- }else {
- return null;
- }
- }
-
- //方法二
- public static Car getBMW(){
- return new BMW();
- }
- public static Car getAudi(){
- return new Audi();
- }
-
-
- }
5.顾客(调用)
- public class Consumer {
- public static void main(String[] args) {
- //接口实现所有类!工厂
- // Car car1 = new BMW();
- // Car car2 = new Audi();
-
- //使用工厂创建
- Car car1 = CarFactory.getCar("宝马");
- Car car2 = CarFactory.getCar("奥迪");
-
- car1.name();
- car2.name();
-
- }
- }
不过这样还是有一些问题,前面提到了开闭原则,一个软件实体,比如类、模块和函数应该对扩展开放,对修改关闭。
此时如果需要新增一种汽车,比如保时捷,那么就得去修改工厂提供的工厂方法了,这样是不太符合开闭原则的。因为工厂实际上是针对于调用方提供的,所以应该尽可能对修改关闭。
所以,我们就利用对扩展开放,对修改关闭的性质,将简单工厂模式改进为工厂方法模式,既然不让改,那么就看看如何去使用扩展的形式。
这里还是以汽车工厂生产汽车介绍工厂方法模式(在简单工厂模式上修改):
1.定义汽车工厂
- public interface CarFactory {
- Car getCar();
- }
2.定义BMW工厂
- public class BMWFactory implements CarFactory{
- @Override
- public Car getCar() {
- return new BMW();
- }
- }
3.定义Audi工厂
- public class AudiFactory implements CarFactory{
- @Override
- public Car getCar() {
- return new Audi();
- }
- }
4.增加Tesla
①定义Tesla类
- public class Tesla implements Car{
- @Override
- public void name() {
- System.out.println("特斯拉");
- }
- }
②定义Tesla工厂
- public class TeslaFactory implements CarFactory{
- @Override
- public Car getCar() {
- return new Tesla();
- }
- }
这样,就可以使用不同类型的工厂来生产不同类型的汽车了,如果新增了汽车类型,直接创建一个新的工厂类就行,不需要修改之前已经编写好的内容。
5.顾客(调用)
- public class Consumer {
- public static void main(String[] args) {
- Car car1 = new BMWFactory().getCar();
- Car car2 = new AudiFactory().getCar();
- Car car3 = new TeslaFactory().getCar();
-
- car1.name();
- car2.name();
- car3.name();
- }
- }
这样,就简单实现了工厂方法模式,通过工厂来屏蔽对象的创建细节,使用者只需要关心如何去使用对象即可。
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new
就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。