一文搞懂工厂模式

251 阅读4分钟

工厂模式

工厂模式是我们最常用的设计模式之一,使用工厂方法替代new操作。工厂模式又分为三种,分别是简单工厂,工厂方法和抽象工厂。

简单工厂

定义一个工厂类,根据传入的参数来决定实例化哪个类:

public interface Mouse {
    void sayHello();
}
public class DellMouse implements Mouse {
    @Override
    public void sayHello() {
        System.out.println("你好,我是戴尔鼠标");
    }
}
public class LenovoMouse implements Mouse {
    @Override
    public void sayHello() {
        System.out.println("你好,我是联想鼠标");
    }
}
// 鼠标工厂类,负责创建鼠标实例
public class MouseFactory {

    public static Mouse createMouse(int type){
        switch (type){
            case 1:
                return new DellMouse();
            case 2:
                return new LenovoMouse();
            default:
                return null;
        }
    }
}

来简单测试一下结果:

public static void main(String[] args) {
        Mouse dell = MouseFactory.createMouse(1);
        dell.sayHello();
        Mouse lenovo = MouseFactory.createMouse(2);
        lenovo.sayHello();
 }

控制台输出的结果:

你好,我是戴尔鼠标 你好,我是联想鼠标

可以看到MouseFactory工厂类可以根据传入的type决定实例化哪个Mouse的实现类。

优点

对创建对象的过程进行屏蔽,对客户端屏蔽细节。

缺点

缺点也是显而易见,假如创建对象的过程并不是简单的new LenovoMouse()或者new DellMouse()而是一大段初始化逻辑,又或者是Mouse的子类非常的多,简单工厂中createMouse方法将会变得非常臃肿。并且增加或删除对应的Mouse子类都需要去修改工厂类中的代码,违反了开闭原则。

工厂方法

工厂方法在简单工厂的基础上做了升级,将工厂类向下扩展,把创建对象的逻辑交由具体的子类工厂去完成。

在Mouse接口及其两个子类LenovoMouse和DellMouse不变的情况下,增加三个类:

// 工厂接口,创建逻辑交由具体子类去完成
public interface MouseFactory {
    Mouse createMouse();
}

public class LenovoMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse() {
        return new LenovoMouse();
    }
}

public class DellMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }
}

继续类测试一下结果:

public static void main(String[] args) {

    MouseFactory dellMouseFactory = new DellMouseFactory();
    Mouse dellMouse = dellMouseFactory.createMouse();
    dellMouse.sayHello();
    MouseFactory lenovoFactory = new LenovoMouseFactory();
    Mouse lenovoMouse = lenovoFactory.createMouse();
    lenovoMouse.sayHello();

}

控制台输出: 你好,我是戴尔鼠标 你好,我是联想鼠标

优点

在简单工厂优点的基础上,工厂方法做了升级,符合开闭原则,单一责任原则,比如要增加一个Mouse的子类,那么只需要添加一个工厂子类去创建对应的Mouse子类即可,不需要改动工厂接口,并且每一种工厂只负责创建一个实例。

缺点

每添加一个Mouse的子类,就需要添加一个工厂类,项目中的类会变得非常多。

再者该工厂只能创建一类产品的创建,假如我们需要创建一系列产品 ,比如我想创建鼠标和键盘两种产品,工厂方法模式是做不到的。

抽象工厂

继而,在工厂方法的基础上,衍生出了抽象方法模式。抽象工厂提供创建一系列相关或相互依赖对象的接口。

同样,在Mouse接口及其两个子类LenovoMouse和DellMouse不变的情况下做修改

// 键盘实例接口
public interface Keyboard {
    void sayHello();
}
// 联想键盘
public class LenovoKeyboard implements Keyboard {
    @Override
    public void sayHello() {
        System.out.println("你好,我是联想键盘");
    }
}
// 戴尔键盘
public class DellKeyboard implements Keyboard {
    @Override
    public void sayHello() {
        System.out.println("你好,我是戴尔键盘");
    }
}
// 生产鼠标和键盘的工厂
public interface ComputerFactory {
    /**
     * 创建鼠标实例
     * @return
     */
    Mouse createMouse();
    /**
     * 创建键盘实例
     * @return
     */
    Keyboard createKeyboard();
}
// 联想鼠标和键盘工厂
public class LenovoComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new LenovoMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new LenovoKeyboard();
    }
}
// 戴尔鼠标和键盘工厂
public class DellComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new DellKeyboard();
    }
}

继续测试:

public static void main(String[] args) {

    ComputerFactory lenovoComputerFactory = new LenovoComputerFactory();
    Keyboard lenovoKeyboard = lenovoComputerFactory.createKeyboard();
    lenovoKeyboard.sayHello();
    Mouse lenovoMouse = lenovoComputerFactory.createMouse();
    lenovoMouse.sayHello();

    ComputerFactory dellComputerFactory = new DellComputerFactory();
    Mouse dellMouse = dellComputerFactory.createMouse();
    dellMouse.sayHello();
    Keyboard dellKeyboard = dellComputerFactory.createKeyboard();
    dellKeyboard.sayHello();
}

控制台输出: 你好,我是联想键盘 你好,我是联想鼠标 你好,我是戴尔鼠标 你好,我是戴尔键盘

优点

抽象工厂除了具有工厂方法的优点外,能够创建产品族,解决了工厂方法只支持生产一种产品的弊端。

缺点

抽象工厂依旧存在工厂方法的缺点,扩展起来类太多,关系负责,并且扩展一种产品的时候需要修改具体的工厂生产接口,违背了开闭原则。

总结

抽象工厂:每个抽象产品派生多个具体的产品类,每个抽象工厂类派生出多个具体的工厂类,每个具体的工厂类负责一系列具体产品的创建

工厂方法:每个抽象产品派生多个具体的产品类,每个抽象工厂类派生出多个具体的工厂类,每个具体的工厂类负责一个具体产品的创建

可以根据不同的场景选择合适的工厂模式