「设计模式」- 浅谈工厂模式

255 阅读4分钟

这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战

1. 前言

对于工厂模式来说,相关的设计模式有三个,都是创建型的设计模式,先简单介绍一下:

  1. 简单工厂模式:在简单工厂模式中,把实例化的操作单独放到一个工厂类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。
  2. 工厂方法:定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
  3. 抽象工厂:抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。

2 简单工厂模式

2.1 类图

如下图所示,在简单工厂模式中,把实例化的操作单独放到 SimpleFactory 中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。

这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。


2.2 实现方式

public interface IProduct {
}
public class Product1 implements Product {
}
public class Product2 implements Product {
}

以下是实例化对象的简单工厂类

public class SimpleFactory {
    public Product createProduct(String type) {
        if ("冰箱".equal(type)) {
            return new Product1();
        }
        return new Product2();
    }
}

以下是 Client 的调用方式

public class Client {
    public static void main(String[] args) {
        SimpleFactory simpleFactory = new SimpleFactory();
        Product product = simpleFactory.createProduct("冰箱");
    }
}

2.3 简单工厂模式小结

简单工厂模式的缺点:

  1. 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
  2. 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
  3. 统扩展困难,一旦添加新产品就不得不修改工厂逻辑,同样破坏了“开闭原则”
  4. 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构

只有工厂负责创建的对象比较少,才能使用这个设计模式,并且简单工厂模式在添加新类时是要修改原有代码的,这违背了开闭原则。


3. 工厂方法模式

3.1 类图

下图所示,在 Factory 中抽象出一个创建产品的方法,但是没有具体的实现逻辑,而是交给其子类去实现。


3.2 实现

假设有三个产品对象需要创建,ProductProduct1Product2,创建三个工厂类分别去实现创建的具体逻辑,这样做的好处是当有新产品增加,只需要增加新的工厂类就行了。

public abstract class Factory {
    abstract public Product factoryMethod();
    public void doSomething() {
        Product product = factoryMethod();
    }
}
public class ConcreteFactory extends Factory {
    public Product factoryMethod() {
        return new Product();
    }
}
public class ConcreteFactory1 extends Factory {
    public Product factoryMethod() {
        return new Product1();
    }
}
public class ConcreteFactory2 extends Factory {
    public Product factoryMethod() {
        return new Product2();
    }
}

3.3 简单工厂模式小结

工厂方法模式很好的体现了 依赖倒置原则:不能让高层组件依赖于低层组件,而且不管高层组件还是低层组件,都应该依赖于抽象。

工厂方法的缺点是当每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。


4. 抽象工厂模式

4.1 类图

抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 createProductA()createProductB() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义。

至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。

从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。


4.2 实现

public class AbstractProductA {
}
public class AbstractProductB {
}
public class ProductA extends AbstractProductA {
}
public class ProductB extends AbstractProductB {
}
public abstract class AbstractFactory {
    abstract AbstractProductA createProductA();
    abstract AbstractProductB createProductB();
}
public class ConcreteFactory extends AbstractFactory {
    AbstractProductA createProductA() {
        return new ProductA();
    }

    AbstractProductB createProductB() {
        return new ProductB();
    }
}

Client 中使用 ConcreteFactory 同时创建了两个对象。

public class Client {
    public static void main(String[] args) {
        AbstractFactory abstractFactory = new ConcreteFactory();
        AbstractProductA productA = abstractFactory.createProductA();
        AbstractProductB productB = abstractFactory.createProductB();
    }
}

4.3 抽象工厂小结

抽象工厂模式实现的关键点是定义工厂接口和产品接口,但如何实现工厂与产品本身需要留给具体的子类实现,客户端只和抽象工厂与抽象产品打交道