工厂模式:工厂方法模式和抽象工厂模式

470 阅读5分钟

我们常说的工厂模式并不是一种具体的设计模式。在「GoF设计模式(23种经典设计模式)」里,具体的“工厂模式”是指:工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstract Factory Pattern)。但我们常把简单工厂模式(Simple Factory Pattern)、工厂方法模式、抽象工厂模式统一称为工厂模式。

简单工厂模式(Simple Factory Pattern)

简单工厂也叫静态工厂。简单工厂模式并不是一种设计模式,或者说它不在Gof归纳的设计模式里。它是我们的一种设计方法。当我们创建对象时,一般通过new的方式创建,而这种方式创建就是面向实现方式编程(当我们对象已经确定时,相关的功能就已经确定了)。

使用简单工厂模式创建对象的好处:

  • 简单方便获取对象

  • 可以使创建对象的细节与业务代码分割开来,封装并隐藏对象创建的细节

  • 创建对象的方式修改了,只需要修改工厂里的方法,而不需要在每个调用方修改。

简单工厂方法实现起来,非常简单:

// 抽象产品接口
public interface IProduct {
    void display();
}

//产品A
public class AProduct implements IProduct {
    @Override
    public void display() {
        System.out.println("我是A产品");
    }
}
// 产品B
public class BProduct implements IProduct {
    @Override
    public void display() {
        System.out.println("我是B产品");
    }
}
// 简单工厂
public class SimpleFactory {
    public static IProduct createProduct(String type) {
        if ("A".equals(type)) {
            return new AProduct();
        }
        if ("B".equals(type)) {
            return new BProduct();
        }
        return null;
    }

    public static void main(String[] args) {
        // A产品
        IProduct aProduct = SimpleFactory.createProduct("A");
        aProduct.display();
        // B产品
        IProduct bProduct = SimpleFactory.createProduct("B");
        bProduct.display();
    }
}
输出结果:
我是A产品
我是B产品

简单工厂实现起来很简单,但也有一定弊端,主要是违法了开闭原则(对扩展开放,对修改关闭),当需要增加新的产品时,我们需要修改简单工厂里的静态方法。

工厂方法模式(Factory Method Pattern)

工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

工厂方法模式包含四种角色:抽象产品,具体产品,抽象工厂,具体工厂

具体产品(具体对象),由具体工厂方法创建。

用代码演示如下

// 抽象产品
public interface IProduct {
    void display();
}

//具体产品A
public class AProduct implements IProduct {
    @Override
    public void display() {
        System.out.println("我是A产品");
    }
}
// 具体产品B
public class BProduct implements IProduct {
    @Override
    public void display() {
        System.out.println("我是B产品");
    }
}
// 抽象工厂
public interface IProductFactory {
    IProduct createProduct();
}
// 具体工厂A
public class ProductAFactory implements IProductFactory {
    @Override
    public IProduct createProduct() {
        return new AProduct();
    }

}
// 具体工厂B
public class ProductBFactory implements IProductFactory {
    @Override
    public IProduct createProduct() {
        return new BProduct();
    }
}
// 客户端演示
public class Client {
    public static void main(String[] args) {
        // A产品工厂
        IProductFactory aProductFactory = new ProductAFactory();
        // 创建A产品
        IProduct aProduct = aProductFactory.createProduct();
        aProduct.display();
        // B产品工厂
        IProductFactory bProductFactory = new ProductBFactory();
        // 创建B产品
        IProduct bProduct = bProductFactory.createProduct();
        bProduct.display();
    }
}
输出结果:
我是A产品
我是B产品

如果我们需要新增「产品C」,只需要增加一个「产品C」的实现类和「产品C」的具体工厂。

工厂方法模式相对简单工厂方法来说,主要是实现了对修改关闭(若要修改,只需要新增一个子类)。

工厂方法模式中的「让一个类的实例化延迟到其子类」,是增加系统扩展性的重要方式。

当然,从演示代码来看,在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口。

抽象工厂模式与工厂方法类似,都是通过具体工厂来创建具体产品。但抽象工厂不是创造一类产品(所有具体产品都是实现(继承)同一个抽象产品,所以归为一类产品),而是创建一系列相关或相互依赖的产品。什么是一系列或相互依赖的产品来说呢?举一个现实中例子,冰箱是一类产品,实际有海尔冰箱、美的冰箱等。而一系列产品就是同一品牌下的不同产品,比如海尔系列的:海尔冰箱、海尔空调、海尔洗衣机;美的系列的:美的冰箱、美的空调、美的洗衣机。通常,一系列的产品也被称为“产品族”

用代码演示抽象工厂演示如下:

// 抽象卡券
public interface ICard {
    void display();
}
// 抽象产品
public interface IProduct {
    void display();
}
// A系列产品
public class AProduct implements IProduct {
    @Override
    public void display() {
        System.out.println("我是A产品");
    }
}
// A系统卡券
public class ACard implements ICard {
    @Override
    public void display() {
        System.out.println("我是A卡券");
    }
}
// B系列产品
public class BProduct implements IProduct {
    @Override
    public void display() {
        System.out.println("我是B产品");
    }
}
// B系列卡券
public class BCard implements ICard {
    @Override
    public void display() {
        System.out.println("我是B卡券");
    }
}
// 抽象工厂,创建相互依赖或相关的产品
public interface AbstractFactory {
    /**
     * 创建商品
     * @return
     */
    IProduct createProduct();

    /**
     * 创建卡券
     * @return
     */
    ICard createCard();
}
// A系列工厂
public class AFactory implements AbstractFactory {
    @Override
    public IProduct createProduct() {
        return new AProduct();
    }

    @Override
    public ICard createCard() {
        return new ACard();
    }
}
// B系列工厂
public class BFactory implements AbstractFactory {
    @Override
    public IProduct createProduct() {
        return new BProduct();
    }

    @Override
    public ICard createCard() {
        return new BCard();
    }
}
// 客户端
public class Client {
    public static void main(String[] args) {
        // A系统产品
        AbstractFactory aFactory = new AFactory();
        IProduct aProduct = aFactory.createProduct();
        ICard aCard = aFactory.createCard();
        aProduct.display();
        aCard.display();

        // B系列产品
        AbstractFactory bFactory = new BFactory();
        IProduct bProduct = bFactory.createProduct();
        ICard bCard = bFactory.createCard();
        bProduct.display();
        bCard.display();
    }
}

输出结果:
我是A产品
我是A卡券
我是B产品
我是B卡券

抽象工厂可以创建一系列产品,但其有一个弊端,在产品族中新增一个产品,其所有具体工厂,都需要重新实现一个创建新产品的方法。