简单工厂到工厂模式的演进

简单工厂定义

定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式。

简单工厂UML类图

案例:实现一个简单的计算器

假设我们实现一个简单的计算器程序,能进行加、减、乘、除四种基本运算。

实现:简单工厂

每种运算都是一个操作类,它们都继承自一个共同的接口或抽象类,叫Operation

操作类

  1. Addition:实现Operation接口,执行加法运算。
  2. Subtraction:实现Operation接口,执行减法运算。
  3. Multiplication:实现Operation接口,执行乘法运算。
  4. Division:实现Operation接口,执行除法运算。

简单工厂类

CalculatorFactory:这个工厂类提供一个方法,比如叫做createOperation,它接受一个参数来决定需要创建哪种运算类的实例。

客户端代码

客户端代码不需要知道具体的操作类,只需要知道工厂类和操作接口。客户端通过传递一个标识符给工厂类,然后工厂类返回相应的操作类的实例。

示例代码

// 操作接口
interface Operation {
    public int operate(int a, int b);
}

// 加法类
class Addition implements Operation {
    public int operate(int a, int b) {
        return a + b;
    }
}

// 减法类
class Subtraction implements Operation {
    public int operate(int a, int b) {
        return a - b;
    }
}

// 乘法类
class Multiplication implements Operation {
    public int operate(int a, int b) {
        return a * b;
    }
}

// 除法类
class Division implements Operation {
    public int operate(int a, int b) {
        if (b != 0) {
            return a / b;
        } else {
            throw new IllegalArgumentException("除数不能为0");
        }
    }
}

// 简单工厂类
class CalculatorFactory {
    public Operation createOperation(String operation) {
        switch (operation) {
            case "ADD":
                return new Addition();
            case "SUB":
                return new Subtraction();
            case "MUL":
                return new Multiplication();
            case "DIV":
                return new Division();
            default:
                throw new IllegalArgumentException("无效的操作");
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        CalculatorFactory calculatorFactory = new CalculatorFactory();
        Operation add = calculatorFactory.createOperation("ADD");
        Operation sub = calculatorFactory.createOperation("SUB");
        Operation mul = calculatorFactory.createOperation("MUL");
        Operation div = calculatorFactory.createOperation("DIV");

        int result = add.operate(10, 5);
        System.out.println("10 + 5 = " + result);

        result = sub.operate(10, 5);
        System.out.println("10 - 5 = " + result);

        result = mul.operate(10, 5);
        System.out.println("10 * 5 = " + result);

        result = div.operate(10, 5);
        System.out.println("10 / 5 = " + result);
    }
}

在这个例子中,CalculatorFactory是一个简单工厂,它根据传入的字符串参数创建并返回相应的Operation对象。客户端代码只需要与工厂和操作接口交互,而不需要知道具体的操作类,这使得系统更加灵活和易于扩展。

思考:简单工厂存在的问题

工厂类是一个“巨大的”类,在该类的设计中存在如下几个问题:

(1)包含很多 if…else… 代码块,整个类的代码相当冗长,代码越长,阅读难度、维护难度和测试难度也越大;而且大量条件语句的存在还将影响系统的性能,程序在执行过程中需要做大量的条件判断。

(2) 当需要增加新的操作时,如求平方和,必须修改工厂类的源代码,违反了“开闭原则”(对扩展开放,对修改关闭)。

注:当前这个例子比较简单,因此缺点不明显。

在简单工厂模式中,所有的产品都由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题。

工厂方法定义

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个创建对象的接口,但让实现这个接口的子类来决定实例化哪一个类。工厂方法模式使得类的实例化推迟到子类中进行。这种模式特别适用于当对象的创建过程比较复杂,或者对象的创建依赖于一些配置或环境因素时。

工厂方法UML类图

实现:使用工厂方法模式重构

使用工厂方法模式进行重构

  1. 定义产品接口:所有产品对象实现的接口。
  2. 创建具体产品类:实现产品接口的具体类。
  3. 定义工厂接口:所有工厂类实现的接口,包含一个工厂方法。
  4. 创建具体工厂类:实现工厂接口的具体工厂类,负责实例化具体的产品对象。

重构后的代码示例

产品接口和具体产品类
// 产品接口
interface Operation {
    int operate(int a, int b);
}

// 具体产品类
class Addition implements Operation {
    public int operate(int a, int b) {
        return a + b;
    }
}

class Subtraction implements Operation {
    public int operate(int a, int b) {
        return a - b;
    }
}

class Multiplication implements Operation {
    public int operate(int a, int b) {
        return a * b;
    }
}

class Division implements Operation {
    public int operate(int a, int b) {
        if (b != 0) {
            return a / b;
        } else {
            throw new IllegalArgumentException("除数不能为0");
        }
    }
}
工厂接口和具体工厂类
// 工厂接口
interface OperationFactory {
    Operation createOperation();
}

// 具体工厂类
class AdditionFactory implements OperationFactory {
    public Operation createOperation() {
        return new Addition();
    }
}

class SubtractionFactory implements OperationFactory {
    public Operation createOperation() {
        return new Subtraction();
    }
}

class MultiplicationFactory implements OperationFactory {
    public Operation createOperation() {
        return new Multiplication();
    }
}

class DivisionFactory implements OperationFactory {
    public Operation createOperation() {
        return new Division();
    }
}
客户端代码
public class Client {
    public static void main(String[] args) {
        OperationFactory factory;

        // 根据需要创建不同的工厂和产品
        factory = new AdditionFactory();
        Operation operation = factory.createOperation();
        System.out.println("10 + 5 = " + operation.operate(10, 5));

        factory = new SubtractionFactory();
        operation = factory.createOperation();
        System.out.println("10 - 5 = " + operation.operate(10, 5));

        factory = new MultiplicationFactory();
        operation = factory.createOperation();
        System.out.println("10 * 5 = " + operation.operate(10, 5));

        factory = new DivisionFactory();
        operation = factory.createOperation();
        System.out.println("10 / 5 = " + operation.operate(10, 5));
    }
}

优化效果

  1. 遵循开闭原则:新增运算类时,只需新增一个具体的工厂类,无需修改现有代码。
  2. 解耦:客户端代码只需知道具体的工厂类,不需要知道具体的产品类,降低了系统的耦合度。
  3. 扩展性:可以轻松地添加新的运算类和相应的工厂类,而不影响现有系统。

通过使用工厂方法模式,我们可以将对象创建的职责分散到多个工厂类中,使得系统更加灵活和易于维护。

如果您在阅读本文时获得了帮助或受到了启发,希望您能够喜欢并收藏这篇文章,为它点赞~
请在评论区与我分享您的想法和心得,一起交流学习,不断进步,遇见更加优秀的自己!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行者无疆1982

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值