Java设计模式-简单工厂模式

114 阅读4分钟

简单工厂模式

1.什么是简单工厂模式

简单工厂模式,大白话来说,就是有一个抽象类,这个抽象类定义了一些属性和一些抽象方法。然后有多个不同的子类继承这个抽象类,并重写抽象方法。 当实例化这个抽象类的时候,对抽象类的属性赋予不同的值,再调用抽象方法,这个抽象方法就可以根据属性值来执行出不同的结果。 简单工厂模式其实就是解决到底要实例化谁,将来会不会增加实例化的对象等问题。而这些问题需要考虑用一个单独的类来做这个创造示例的过程,这个就是工厂类。

2.简单工厂代码示例

2.1抽象Animal父类

/**
 * Animal接口
 */
public abstract class Animal {

    /**
     * 定义一个抽象方法,run
     * 其子类会重写该方法
     */
    public abstract void run();
}

2.2 Dog子类

/**
 * 定义Dog类,继承Animal类
 */
public class Dog extends Animal{

    /**
     * Dog类重写Animal类的run方法
     */
    @Override
    public void run() {
        System.out.println("小狗类被创建了,小狗正在跑");
    }
}

2.3Cat子类

/**
 * 定义Cat类,实现Animal接口
 */
public class Cat extends Animal{

    /**
     * Cat类重写Animal的run方法
     */
    @Override
    public void run() {
        System.out.println("小猫类被创建了,小猫正在跑");
    }
}

2.4 Animal工厂类

/**
 * Animal工厂类,根据传入工厂的不同动物名称,
 * 实例化不同的Animal子类对象
 */
public class AnimalFactory {
    /**
     * 工厂的静态创建对象方法
     * @param animalName 动物名称
     * @return Animal抽象类的子类实例
     */
    public static Animal createAnimal(String animalName){
        Animal animal = null;
        switch (animalName){
            case "dog":
            case "小狗":
                animal = new Dog();
                break;
            case "cat":
            case "小猫":
                animal = new Cat();
                break;
        }
        return animal;
    }
}

2.5测试类

public class MainApplication {
    public static void main(String[] args) {
        // 通过Animal工厂创建一个小猫实例对象出来
        Animal factory = AnimalFactory.createAnimal("小猫");
        // 执行新实例对象的run方法
        factory.run();
    }
}

2.6运行结果

image.png

3.简单工厂模式UML类图

image.png

4.简单工厂模式演化分析

下面以实现一个简单计算器为示例,演示一下简单工厂设计模式的演变过程

4.1实现一个最简单的计算器

/**
 * 计算器,简单版本
 */
public class Operation {
    public static double getResult(double numberA, double numberB, String operate){
        double result = 0D;
        switch (operate){
            case "+":
                result = numberA + numberB;
                break;
            case "-":
                result = numberA - numberB;
                break;
            case "/":
            case "÷":
                result = numberA / numberB;
                break;
            case "*":
            case "x":
                result = numberA * numberB;
                break;
        }
        return result;
    }
}

4.2 紧耦合 VS 松耦合

上面这个简单的计算器,虽然能够实现加减乘除的功能,但是从设计上来说,这个代码结构不够灵活。如果此时需要加一个开根运算,就需要在Operation类中,加上新的switch分支,这样对Operation这个类改动太大,侵入太多,如果不小心修改错位置,改掉了以前的代码,还可能会造成旧功能失效或出现新bug。 为了解决这样的问题,我们就可以使用继承和多态的机制,来解决Operation类耦合过高的问题。

4.2.1Operation父类

public class Operation {

    private double numberA = 0D;
    private double numberB = 0D;

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }

    public double getResult(){
        return 0D;
    }

}

4.2.2加法子类

public class OperationAdd extends Operation{
    @Override
    public double getResult() {
        return getNumberA() + getNumberB();
    }
}

4.2.3减法子类

public class OperationSub extends Operation{
    @Override
    public double getResult() {
        return getNumberA() - getNumberB();
    }
}

4.2.4乘法子类

public class OperationMul extends Operation{
    @Override
    public double getResult() {
        return getNumberA() * getNumberB();
    }
}

4.2.5除法子类

public class OperationDiv extends Operation{
    @Override
    public double getResult() {
        if (getNumberB() <= 0) {
            throw new RuntimeException("除数不能为0");
        }
        return getNumberA() / getNumberB();
    }
}

4.3 简单工厂模式

像上面一步那样将Operation类和加减乘除操作分离开来,就可以达到让加减乘除操作和Operation类解耦的目的。因为这样写了之后,当需要扩展其他运算规则的时候,只需要继承Operation父类,并重写父类的getResult方法,即可实现对计算器功能的扩展,根本不需要修改Operation父类和其他已存在的加减乘除子类,避免了对已有功能造成bug的风险。 但是这样又会引出另一个问题,那就是如何让计算器知道,我们具体想要执行的是哪一个算法逻辑呢? 由这个问题,就可以引出简单工厂模式。就是说到底要实例化谁,将来会不会增加实例化的对象,比如增加开根运算等,展示很容易变化的地方,应该考虑用一个单独的类来做这个创造示例的过程,这个类就是工厂。

4.3.1简单工厂代码示例

public class OperationFactory {
    public static Operation createOperate(String operate){
        Operation op = null;
        switch (operate){
            case "+":
                op = new OperationAdd();
                break;
            case "-":
                op = new OperationSub();
                break;
            case "/":
            case "÷":
                op = new OperationDiv();
                break;
            case "*":
            case "x":
                op = new OperationMul();
                break;
        }
        return op;
    }
}

4.3.2 Operation工厂使用

public class MainApplication {
    public static void main(String[] args) {
        Operation operation = OperationFactory.createOperate("+");
        operation.setNumberA(1);
        operation.setNumberB(2);
        System.out.println(operation.getResult());
    }
}

在使用了简单工厂模式后,当需要扩展各种复杂运算,比如平方根,立方根,自然对数等等,只需要继承Operate父类并重写getResult接口即可,这样原计算器的功能就可以很容易被扩展,且不会侵入现有功能。