工厂设计模式

分类

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式可以分为三类:

  • 简单工厂方法——Simple Factory
  • 工厂方法模式——Factory Method
  • 抽象工厂方法——Abstract Factory

1.简单工厂设计模式

所谓的简单工厂就是通过一个工厂类来实现产品的实例化,通常可以在工厂类中定义一个静态方法,通过传入相应的参数来产生相应的产品对象。

//定义一个产品接口
interface IProduct{
    public void desc(); 
}
//定义一个产品A
class ProductA implements IProduct{
    public void desc() {
        System.out.println("Product A");
    }
}
//定义一个产品B
class ProductB implements IProduct{
    public void desc() {
        System.out.println("Product B");
    }
}
//定义一个产品C
class ProductC implements IProduct{
    public void desc() {
        System.out.println("Product C");
    }
}
//定义工厂类
class SimpleFactory {
    public static final int PRODUCT_A = 1;
    public static final int PRODUCT_B = 2;
    public static final int PRODUCT_C = 3;
    public static IProduct createProduct( int flag) {
        switch(flag) {
        case PRODUCT_A:
            return new ProductA();
        case PRODUCT_B:
            return new ProductB();
        case PRODUCT_C:
        default:
            return new ProductC();
        }
    }
}
public class FactoryMode {

    public static void main(String[] args) {
        // 简单工厂设计模式:实例化产品A
        IProduct iproduct = SimpleFactory.createProduct(SimpleFactory.PRODUCT_A);
        iproduct.desc();
    }
}

使用场景:工厂类负责创建的对象比较少,客户只需要传入工厂类参数,对于如何创建对象(逻辑)不关心。简单工厂模式很容易违反高内聚低耦合的原则,因此一般只在很简单的情况下使用。
优点:最大的优点在于工厂类中包含了必要的逻辑,根据客户需要的逻辑动态实例化相关的类。
缺点:扩展性差,每次新增产品时都需要修改工厂类方法。
此外简单工厂还有一种写法:通过多个静态方式实现

class SimpleFactory {
    public static IProduct createProductA() {
        return new ProductA(); //生产产品A
    }
    public static IProduct createProductB() {
        return new ProductB(); //生产产品B
    }
    public static IProduct createProductC() {
        return new ProductC(); //生产产品C
    }
}
public class FactoryMode {

    public static void main(String[] args) {
        // 简单工厂设计模式:实例化产品A
        IProduct iproduct = SimpleFactory.createProductA();
        iproduct.desc();
    }
}

这种写法的好处就是在新增产品时,只需要增加相应的静态方法即可,而不需要修改原有方法的逻辑。

2.工厂方法模式

简单说就是一种产品对应一个工厂类,这些工厂类都继承/实现一个抽象工厂类/工厂接口。

如下图所示:

java使用工厂方法创建对象_java使用工厂方法创建对象


代码如下:

创建工厂类

//产品A对应的工厂方法
class FactoryProductA implements IFactory{
    @Override
    public IProduct createProduct() {
        return new ProductA();
    }
}
//产品B对应的工厂方法
class FactoryProductB implements IFactory{
    @Override
    public IProduct createProduct() {
        return new ProductB();
    }
}
//产品C对应的工厂方法
class FactoryProductC implements IFactory{
    @Override
    public IProduct createProduct() {
        return new ProductC();
    }
}

客户端

public class FactoryMode {
    public static void main(String[] args) {
        // 工厂方法:实例化产品A
        FactoryProductA fpa = new FactoryProductA();
        ProductA pA = (ProductA)fpa.createProduct();
        pA.desc();
        // 工厂方法:实例化产品B
        FactoryProductB fpb = new FactoryProductB();
        ProductB pb = (ProductB)fpb.createProduct();
        pb.desc();
    }
}

优点:创建对象的接口,让子类决定具体实例化的对象,把简单的内部逻辑判断移到了客户端。扩展性高,想要增加一个产品,只要扩展一个工厂类就可以。工厂方法模式克服了简单工厂所违背的开闭原则的缺点,又保持了封装对象创建过程的优点。
缺点:当产品种类非常多时,需要建立非常多的工厂类,这不是我们希望的。
使用场景

  • 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
  • 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
  • 设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。

3.抽象工厂方法

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。

如下图所示:

java使用工厂方法创建对象_java使用工厂方法创建对象_02


还是以汽车为例,汽车A配备A型号发动机+A型号空调,汽车B配备B型号发动机+B型号空调,根据客户需求生产这种车。

定义产品1—空调(Aircondition):

interface IAirCondition{
    public void desc(); 
}

class AirConditionA implements IAirCondition{
    @Override
    public void desc() {
        System.out.println("Air Condition A");
    }
}
class AirConditionB implements IAirCondition{
    @Override
    public void desc() {
        System.out.println("Air Condition B");
    }
}

定义产品2—引擎(Engine):

interface IEngine{
    public void desc(); 
}

class EngineA implements IEngine{
    @Override
    public void desc() {
        System.out.println("Engine A");
    }
}
class EngineB implements IEngine{
    @Override
    public void desc() {
        System.out.println("Engine B");
    }
}

定义工厂类:

interface IFactory{
    public IEngine createEngine();
    public IAirCondition createAirConditon();
}

//CarA对应的工厂方法
class FactoryCarA implements IFactory{
    @Override
    public IEngine createIEngine() {
        return new EngineA();
    }
    @Override
    public IAirCondition createAirConditon() {
        return new AirConditionA();
    }
}
//CarB对应的工厂方法
class FactoryCarB implements IFactory{
    @Override
    public IEngine createIEngine() {
        return new EngineB();
    }
    @Override
    public IAirCondition createAirConditon() {
        return new AirConditionB();
    }
}

客户端

public class FactoryMode {
    public static void main(String[] args) {
        FactoryCarA fa = new FactoryCarA();
        fa.createAirConditon().desc();
        fa.createEngine().desc();

        FactoryCarB fb = new FactoryCarB();
        fb.createAirConditon().desc();
        fb.createEngine().desc();
    }
}

使用场景:当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。

ps:理解产品族和等级结构概念。

(1) 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

(2) 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。

以下为例:

java使用工厂方法创建对象_java使用工厂方法创建对象_03


在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。

明白了等级结构和产品族的概念,就理解工厂方法模式和抽象工厂模式的区别了,如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。在本例中,如果一个工厂模式提供2.0排量两厢车和2.4排量两厢车,那么他属于工厂方法模式;如果一个工厂模式是提供2.4排量两厢车和2.4排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。