0%

设计模式之工厂方法模式

前言

简单工厂模式(静态方法工厂)存在着一系列问题:

  • 工厂类集中了所有的实例(产品)的创建逻辑,一旦这个类进行修改不能正常工作,整个系统都会受到影响
  • 违背“开放-关闭原则”,一旦添加新产品就不得不去修改工厂类的逻辑,这样就会造成工厂逻辑臃肿切过于复杂
  • 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的登记结构

我们为了解决上面的问题,我们需要使用一个新的设计模式:工厂方法模式

工厂方法模式(Factory Method)

定义:

工厂方法模式的作用就是封装对象的创建,由子类决定创建对象是什么。

适用范围:

  • 工厂方法模式是new一个对象的替代品,所以在有需要生成对象的地方都可以使用,但是要慎重的考虑当前任务是不是需要增加一个工厂类进行管理,避免使自己的代码更加复杂。
  • 需要灵活、可扩展的框架时,可以考虑采用工厂方法模式。

说明:

  • Camera

    相机抽象类的抽象,由具体的实现相机类去实现

  • CanonCamera

    具体的佳能相机类,可以有多个,继承于Camera

  • Factory

    抽象工厂类,负责定义产品对象的产生

  • CameraFactory

    具体的工厂实现类,继承于Factory。

我们那个相机举例子,我们的相机是一个产品,不同牌子的相机有不同的特点,也由不同厂家来生产。我们先抽象出对应的相机产品。

相机相关类

1
package com.yubulang.factorymethod;
2
3
// 相机产品的抽象
4
public abstract class Camera {
5
    public abstract void focus();
6
    public abstract void screen();
7
}

有了相机的抽象,我们需要的是实现实现类:

佳能相机实现类

1
package com.yubulang.factorymethod;
2
3
public class CanonCamera extends Camera {
4
    @Override
5
    public void focus() {
6
        System.out.println("佳能对焦系统");
7
    }
8
9
    @Override
10
    public void screen() {
11
        System.out.println("佳能拍照");
12
    }
13
}

尼康相机实现类

1
package com.yubulang.factorymethod;
2
3
public class NikonCamera extends Camera {
4
    @Override
5
    public void focus() {
6
        System.out.println("尼康对焦系统");
7
    }
8
9
    @Override
10
    public void screen() {
11
        System.out.println("尼康拍摄");
12
    }
13
}

工厂相关类——用于生产相机相关

抽象工厂类:

1
package com.yubulang.factorymethod;
2
3
public abstract class Factory {
4
    public abstract <T> T getCamera(Class<T> clz);
5
}

实现一个相机工厂类:

1
package com.yubulang.factorymethod;
2
3
public class CameraFactory extends Factory {
4
    @Override
5
    public <T> T getCamera(Class<T> clz) {
6
        Camera camera = null;
7
8
        try {
9
            camera = (Camera) Class.forName(clz.getName()).newInstance();
10
        } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
11
            e.printStackTrace();
12
        }
13
14
        return (T) camera;
15
    }
16
}

有了对应的工厂我们就必须让对应的工厂为我们生产对应的相机产品。我们调用者只用找对应的工厂生产对应的产品就好了。

1
package com.yubulang.factorymethod;
2
3
public class Photographer {
4
    public static void main(String[] args) {
5
        // 作为调用者,我们要使用对应的相机,就叫对应的工厂去给我们生产就好了
6
        CameraFactory cameraFactory = new CameraFactory();
7
8
        CanonCamera canonCamera = cameraFactory.getCamera(CanonCamera.class);
9
        canonCamera.focus();
10
        canonCamera.screen();
11
12
        NikonCamera nikonCamera = cameraFactory.getCamera(NikonCamera.class);
13
        nikonCamera.focus();
14
        nikonCamera.screen();
15
    }
16
}

工厂方法模式的优缺点

优点:

  • 良好的封装性,代码结构清晰

    不需要知道对象的创建过程,降低模块间的耦合

  • 工厂方法模式的拓展性非常优秀

    在增加产品类的情况下,只需要修改具体的工厂类,或者拓展一个工厂内就可以拥抱变化。

  • 屏蔽产品类

    类的任何变化,调用者无需关心,他只需要关心产品的接口。

  • 典型的解耦框架

    高层模块只需要知道产品的抽象类,其他的实现类无需关心,迪米特原则,我们不需要就不要去交流,符合依赖倒置原则,只依赖产品的抽象,符合里式替换原则,使用产品子类替换产品父类,当然也没问题

缺点:

  • 类结构的复杂化:

    每次为工厂方法模式添加新产品都需要写一个新的产品类,还要引入抽象层。

总结

具体还是要看业务怎么样来决定这些设计模式的使用。