设计模式-简单工厂

 阅读约 13 分钟

前言

  大家好我是不一样的科技宅,每天进步一点点,体验不一样的生活,今天我们聊一聊简单工厂模式,虽然不在23种设计模式中。但是可以认为是工厂模式的一种特殊实现,并且在日常中使用广泛,所以还是值得我们去学习的。

定义

  • 简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,是一种创建型的设计模式,关注于实例对象创建。

    • 由一个工厂对象通过判断传入的参数,决定创建出哪一种产品类的实例,将创建的细节透明化。

  注意:简单工厂不属于GOF23种之一。

场景

  在周一阳光明媚的上午,刚带上耳机,准备开始一天的工作,老板突然来到你身旁。

  • 老板: xxx啊,听说你是学计算机的?
  • 我:是的,学的是软件工程。
  • 老板:那帮我组装一台苹果电脑出来吧,周五送到我办公桌上。
  • 我:内心OS:修电脑,我也就认了,这竟然让我组装一台苹果电脑,你咋不上天呢?
  • 老板:预算5000,记得不要超支了。
  • 我:内心虽然波涛汹涌,但是还是说了声,好的老板

  于是我就立马打开chrome,上各大论坛搜索完美黑苹果配置,在初步确定好配置后,就开始上京东,开始选购CPU,主板,固态,内存,电源等配件。在经历了两天的等待,所有配件终于到齐以后,耗费九牛二虎之力,终于在周五前把电脑给组装好了。

  可是呢没过多久,总经理也找我说让我帮他组一台苹果电脑,和老板同样的套路,我能咋办,我也很无耐,但是给的预算更低只有4000于是我也只能在原来的基础上缩减一下配置,勉强达到了要求。

  我在想要是每个领导都这样,那我不是得凉凉啊,想到这里我暗自下定决心,对自己说我下次一定要拒绝他们。

优点

  只需要知道产品的名称即可,就可以创建你所需要的对象,而无需知道其创建细节。

缺点

  工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则,如果产品数量过多,维护将变得非常困难。
  注意:使用反射和枚举可以避免频繁修改工厂类。

使用场景

  • 将实例化过程非常复杂的类,通过工厂进行简化,方便业务方使用。
  • 把创建对象的职责集中管理和控制。

小结

  从上面的小故事可以简单的理解为:老板就是需求方,我就是工厂,老板只需要告诉我,他需要什么就好了,不管我如何实现。但是如果需要的产品变更了,我就只能做修改来满足要求。

UML模型

代码实例

BaseComputer

public abstract class BaseComputer {

    /**
     * 开机
     */
    protected abstract void turnOn();

}

MacBookPro

public class MacBookPro extends BaseComputer {

    @Override
    protected void turnOn() {
        System.out.println("MacBook Pro 开机了");
    }
}

ThinkPad

public class ThinkPad extends BaseComputer {

    @Override
    protected void turnOn() {
        System.out.println("Think Pad 开机了");
    }

}

ComputerFactory

public class ComputerFactory {

    /**
     * 创建电脑
     * @param name 名称
     * @return 返回电脑
     */
    public static BaseComputer create(String name){
        if("mac".equals(name)){
            return new MacBookPro();
        }else if("thinkPad".equals(name)){
            return new ThinkPad();
        }else {
            throw new IllegalArgumentException("无法创建"+name+"电脑。");
        }
    }
}

测试

public class Test {

    public static void main(String[] args) {
        BaseComputer mac = ComputerFactory.create("mac");
        mac.turnOn();

        BaseComputer thinkPad = ComputerFactory.create("thinkPad");
        thinkPad.turnOn();

        BaseComputer dell = ComputerFactory.create("dell");
        dell.turnOn();
    }
}

测试结果

MacBook Pro 开机了

Think Pad 开机了

Exception in thread "main" java.lang.IllegalArgumentException: 无法创建dell电脑。
    at simple.factory.ComputerFactory.create(ComputerFactory.java:22)
    at simple.factory.Test.main(Test.java:18)

重构ComputerFactory - Switch

对于ComputerFactory使用if的写法不是很优雅,对此我们可以改成使用switch语句。

注意:Java7以后的版本switch才支持字符串,Java7以前只支持int 、short 、byte 、char
public class ComputerFactory {

    /**
     * 创建电脑
     * @param name 名称
     * @return 返回电脑
     */
    public static BaseComputer create(String name){
        switch (name){
            case "mac":
                return new MacBookPro();
            case "thinkPad":
                return new ThinkPad();
            default:
                throw new IllegalArgumentException("无法创建"+name+"电脑。");
        }
    }
}

重构ComputerFactory - 反射

public class ComputerFactory {

    /**
     * 创建电脑
     * @param name 名称
     * @return 返回电脑
     */
    public static BaseComputer create(String name) {
        BaseComputer computer;
        try {
            computer = (BaseComputer) Class.forName(name).getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e ) {
            throw new IllegalArgumentException("无法创建"+name+"电脑。");
        }
        return computer;
    }
}

测试类

public class Test {

    public static void main(String[] args) {
        BaseComputer mac = ComputerFactory.create("simple.factory.MacBookPro");
        mac.turnOn();

        BaseComputer thinkPad = ComputerFactory.create("simple.factory.ThinkPad");
        thinkPad.turnOn();

        BaseComputer dell = ComputerFactory.create("simple.factory.Dell");
        dell.turnOn();
    }
}

重构ComputerFactory - 反射 + 枚举

public class ComputerFactory {

    /**
     * 创建电脑
     * @param name 名称
     * @return 返回电脑
     */
    public static BaseComputer create(ComputerEnum name) {
        BaseComputer computer;
        try {
            computer = (BaseComputer) name.getClazz().newInstance();
        } catch (InstantiationException | IllegalAccessException e ) {
            throw new IllegalArgumentException("无法创建"+name+"电脑。");
        }
        return computer;
    }
}

电脑枚举类

public enum ComputerEnum {

    /**
     * 电脑枚举类
     */

    MAC_BOOK_PRO(MacBookPro.class),

    THINK_PAD(ThinkPad.class),

    ;

    private Class clazz;

    ComputerEnum(Class clazz) {
        this.clazz = clazz;
    }

    public Class getClazz() {
        return clazz;
    }
}

测试类

public class Test {

    public static void main(String[] args) {
        BaseComputer mac = ComputerFactory.create(ComputerEnum.MAC_BOOK_PRO);
        mac.turnOn();

        BaseComputer thinkPad = ComputerFactory.create(ComputerEnum.THINK_PAD);
        thinkPad.turnOn();
        
    }
}

结尾

  如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。

阅读 279更新于 1月21日

推荐阅读
目录