工厂模式

工厂模式

介绍

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

总是引用接口而非实现类,能允许变换子类而不影响调用方,即尽可能面向抽象编程。

原理

工厂模式中主要有三种类型:

  • 简单工厂模式(Simple Factory Pattern)
  • 工厂方法模式(Factory Method Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)

简单工厂模式(静态工厂方法)

简单工厂模式并不属于23种设计模式之一,它是工厂模式家族中最简单实用的模式。
file

简单工厂模式的工厂类负责创建不同类型的对象,它提供一个创建对象的静态方法,根据传入的参数不同返回不同的类实例。

我们使用MessageDigest时,为了创建某个摘要算法,总是使用静态工厂方法getInstance(String)

MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");

调用方通过产品名称获得产品实例,不但调用简单,而且获得的引用仍然是MessageDigest这个抽象类。

简单工厂模式案例

接口
interface Animal {
    /**
     * 动物叫
     */
    void cry();
    static Animal judge(String name){
        if ("狗".equals(name)){
            return new Dog();
        } else if ("猪".equals(name)) {
            return new Pig();
        }else {
            return null;
        }
    }
}
实现类
class Dog implements Animal {
    public void cry(){
        System.out.println("狗叫");
    }
}
class Pig implements Animal {
    public void cry(){
        System.out.println("猪叫");
    }
}
调用
Animal.judge("狗").cry();
Animal.judge("猪").cry();

输出

狗叫
猪叫

工厂方法模式

工厂方法模式通过定义工厂方法来创建对象,而这个工厂方法可以被子类覆盖,从而改变所创建的对象类型。
一个工厂类对应一个产品类
file

工厂方法模式案例

接口
interface Animal {
    /**
     * 动物叫
     */
    void cry();
}
实现类
class Dog implements Animal {
    public void cry(){
        System.out.println("狗叫");
    }
}
class Pig implements Animal {
    public void cry(){
        System.out.println("猪叫");
    }
}
工厂接口
public interface AnimalFactory {
    Animal getAnimal();
}
工厂类
class DogFactory implements AnimalFactory {
    @Override
    public Animal getAnimal() {
        return new Dog();
    }
}
class PigFactory implements AnimalFactory {
    @Override
    public Animal getAnimal() {
        return new Pig();
    }
}
调用
AnimalFactory animalFactory= new DogFactory();
animalFactory.getAnimal("狗").cry();

输出

狗叫

抽象工厂模式

抽象工厂模式提供了一种将工厂与产品族的概念分离开来的方法,它能够创建一系列相关的对象,而无需指定它们的具体类。
一个品牌或者属性的所有产品(产品族) 对应 一个工厂负责生产(产品族)的所有产品
file

抽象工厂模式案例

接口
interface Animal {
    /**
     * 动物叫
     */
    void cry();
}
interface Botany {
    /**
     * 植物动
     */
    void move();
}
实现类
class Dog implements Animal {
    public void cry(){
        System.out.println("狗叫");
    }
}
class Pig implements Animal {
    public void cry(){
        System.out.println("猪叫");
    }
}
class Grass implements Botany {
    public void move(){
        System.out.println("草在动");
    }
}
class GreenHat implements Botany {
    public void move(){
        System.out.println("绿帽子在动");
    }
}
工厂类
interface Factory {
    Animal getAnimal(String name);
    Botany getBotany(String name);
}
// 草猪
class GrassPig implements Factory{
    public Animal getAnimal(String name){
        return new Pig();
    }
    public Botany getBotany(String name){
        return new Grass();
    }
}
// 绿帽子狗
class GreenHatDog implements Factory{
    public Animal getAnimal(String name){
        return new Dog();
    }
    public Botany getBotany(String name){
        return new GreenHat();
    }
}

工厂模式的优缺点

优点

  1. 可以隐藏创建实现类的过程,让代码更加简洁易懂
  2. 可以避免直接使用 new 关键字来创建对象,降低代码的耦合性

缺点

  1. 增加了代码的复杂度
  2. 增加了程序的抽象性和理解难度

简单工厂的优缺点

优点

  1. 简单上手
  2. 可以创建所有产品

缺点

  1. 如果需要增加额外的类,就违背了开闭原则

工厂方法的优缺点

优点

  1. 解决开闭原则的问题

缺点

  1. 一个工厂只能对应一个产品
  2. 当产品过多时,会出现类爆炸的问题

抽象工厂的优缺点

优点

  1. 解决了类爆炸的问题

缺点

  1. 如果需要增加额外的产品,就违背了开闭原则

注意事项(*重点)

  1. 尽量使用工厂模式来创建对象,而不是直接使用 new 关键字

三者的区别

简单和抽象:违背了开闭原则
工厂方法:类爆炸的问题
简单工厂模式适用于创建逻辑简单的对象
工厂方法模式适用于创建单一类型的对象
抽象工厂模式适用于创建一组相关的产品对象

补充

由于抽象工厂并未解决开闭原则的问题,所以发明了超级工厂和容器工厂

参考文档

廖雪峰的官方网站-工厂方法
工厂模式 | 菜鸟教程