专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

(抽象)工厂模式

示例

实现两数的加、减、乘、除运算。

/**
 * Operation 运算类
 */
public class Operation {

    public static double getResult(double numberA, double numberB, String operate) {
        double result = 0;

        if (Objects.equals(operate, "+")) {
            result = numberA + numberB;
        } else if (Objects.equals(operate, "-")) {
            result = numberA - numberB;
        } else if (Objects.equals(operate, "*")) {
            result = numberA * numberB;
        } else if (Objects.equals(operate, "/")) {
            result = numberA / numberB;
        }

        return result;
    }
}

/**
 * Main
 */
public class Main {

    public static void main(String[] args) {
        double numberA = 20;
        double numberB = 15;
        String operate = "*";

        double result = Operation.getResult(numberA, numberB, operate);

        System.out.println("计算结果是:" + result);
    }
}

上面的实现方式虽然简单且易于理解,但是当我们再增加一个新的运算(比如立方运算)时,就要对 Operation 类中的运算方法进行修改,这样可能会使得本来运行良好的功能代码发生意外的变化,导致程序发生异常。所以我们需要将代码进行改进。

简单工厂模式

简单工厂模式是属于创建型模式,是工厂模式的一种,是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。
简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)。在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

使用简单工厂模式改进

75_1.png

/**
 * Operation
 */
public interface Operation {

    double getResult(double numberA, double numberB);
}

/**
 * OperationAdd 加法运算
 */
public class OperationAdd implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA + numberB;
    }
}

/**
 * OperationSub 减法运算
 */
public class OperationSub implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA - numberB;
    }
}

/**
 * OperationMul 乘法运算
 */
public class OperationMul implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA * numberB;
    }
}

/**
 * OperationDiv 除法运算
 */
public class OperationDiv implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        if (numberB == 0) {
            throw new ArithmeticException("除数不能为 0!");
        }
        return numberA / numberB;
    }
}

/**
 * SimpleFactory
 */
public class SimpleFactory {

    public static Operation newOperation(String operate) {

        Operation operation = null;
        if (Objects.equals(operate, "+")) {
            operation = new OperationAdd();
        } else if (Objects.equals(operate, "-")) {
            operation = new OperationSub();
        } else if (Objects.equals(operate, "*")) {
            operation = new OperationMul();
        } else if (Objects.equals(operate, "/")) {
            operation = new OperationDiv();
        }

        return operation;
    }
}

/**
 * Main
 */
public class Main {

    public static void main(String[] args) {
        double numberA = 20;
        double numberB = 15;
        String operate = "*";

        Operation operation = SimpleFactory.newOperation(operate);
        double result = operation.getResult(numberA, numberB);

        System.out.println(result);
    }
}

如果我们需要对其中的运算进行修改,只需修改它相应的运算类即可;如果需要增加新的运算方式,只需增加相应的运算子类,然后在工厂类里增加一个判断分支,添加相应的实例化代码。

简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是每当要增加一个新的功能时,都要到工厂类的方法里增加一个分支条件,这样就违背了开放封闭原则。

工厂方法模式

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

使用工厂方法模式改进

75_2.png

/**
 * Operation
 */
public interface Operation {

    double getResult(double numberA, double numberB);
}

/**
 * OperationAdd 加法运算
 */
public class OperationAdd implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA + numberB;
    }
}

/**
 * OperationSub 减法运算
 */
public class OperationSub implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA - numberB;
    }
}

/**
 * OperationMul 乘法运算
 */
public class OperationMul implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA * numberB;
    }
}

/**
 * OperationDiv 除法运算
 */
public class OperationDiv implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        if (numberB == 0) {
            throw new ArithmeticException("除数不能为 0!");
        }
        return numberA / numberB;
    }
}

/**
 * IFactory
 */
public interface IFactory {

    Operation newOperation();
}

/**
 * AddFactory 加法工厂类
 */
public class AddFactory implements IFactory {

    @Override
    public Operation newOperation() {
        return new OperationAdd();
    }
}

/**
 * SubFactory 减法工厂类
 */
public class SubFactory implements IFactory {

    @Override
    public Operation newOperation() {
        return new OperationSub();
    }
}

/**
 * MulFactory 乘法工厂类
 */
public class MulFactory implements IFactory {

    @Override
    public Operation newOperation() {
        return new OperationMul();
    }
}

/**
 * DivFactory 除法工厂类
 */
public class DivFactory implements IFactory {

    @Override
    public Operation newOperation() {
        return new OperationDiv();
    }
}

/**
 * Main
 */
public class Main {

    public static void main(String[] args) {
        double numberA = 20;
        double numberB = 15;
        MulFactory mulFactory = new MulFactory();
        Operation operation = mulFactory.newOperation();
        double result = operation.getResult(numberA, numberB);

        System.out.println(result);
    }
}

工厂方法模式,克服了简单工厂模式违背开放封闭原则的缺点,又保持了封装对象创建过程的优点。它们都是集中封装了对象的创建,使得要更换对象时,不需要做大的改动就可实现,降低了客户程序与产品对象的耦合。

工厂方法模式,是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。但缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。

抽象工厂模式

抽象工厂模式定义了一个接口用于创建相关或有依赖关系的对象簇,而无需指明且体的类。抽象工厂模式是将简单工厂模式和工厂方法模式进行整合。从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。将工厂抽象成两层,抽象工厂和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇更利于代码的维护和扩展。

使用抽象工厂模式改进

75_3.png

/**
 * Operation
 */
public interface Operation {

    double getResult(double numberA, double numberB);
}

/**
 * OperationAdd 加法运算
 */
public class OperationAdd implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA + numberB;
    }
}

/**
 * OperationSub 减法运算
 */
public class OperationSub implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA - numberB;
    }
}

/**
 * OperationMul 乘法运算
 */
public class OperationMul implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        return numberA * numberB;
    }
}

/**
 * OperationDiv 除法运算
 */
public class OperationDiv implements Operation {

    @Override
    public double getResult(double numberA, double numberB) {
        if (numberB == 0) {
            throw new ArithmeticException("除数不能为 0!");
        }
        return numberA / numberB;
    }
}

/**
 * OperationAccess 利用反射技术实例化对象
 */
public class OperationAccess {

    public static Operation createOperation(Class<? extends Operation> clazz) {
        Operation operation = null;
        try {
            operation = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return operation;
    }
}

一般来说,所有在用简单工厂的地方,都可以考虑用反射技术来去除 switch 或 if,解除分支判断带来的耦合。

小结

工厂模式是将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到与主项目的依赖关系的解耦目的,从而提高项目的扩展和维护性。创建对象实例时,不要直接 new 类,而是把这个 new 类的动作放在一个工厂的方法中并返回。

未经允许不得转载:搜云库技术团队 » (抽象)工厂模式

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们