简单工厂定义
定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式。
简单工厂UML类图
案例:实现一个简单的计算器
假设我们实现一个简单的计算器程序,能进行加、减、乘、除四种基本运算。
实现:简单工厂
每种运算都是一个操作类,它们都继承自一个共同的接口或抽象类,叫Operation
。
操作类
Addition
:实现Operation
接口,执行加法运算。Subtraction
:实现Operation
接口,执行减法运算。Multiplication
:实现Operation
接口,执行乘法运算。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类图
实现:使用工厂方法模式重构
使用工厂方法模式进行重构
- 定义产品接口:所有产品对象实现的接口。
- 创建具体产品类:实现产品接口的具体类。
- 定义工厂接口:所有工厂类实现的接口,包含一个工厂方法。
- 创建具体工厂类:实现工厂接口的具体工厂类,负责实例化具体的产品对象。
重构后的代码示例
产品接口和具体产品类
// 产品接口
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));
}
}
优化效果
- 遵循开闭原则:新增运算类时,只需新增一个具体的工厂类,无需修改现有代码。
- 解耦:客户端代码只需知道具体的工厂类,不需要知道具体的产品类,降低了系统的耦合度。
- 扩展性:可以轻松地添加新的运算类和相应的工厂类,而不影响现有系统。
通过使用工厂方法模式,我们可以将对象创建的职责分散到多个工厂类中,使得系统更加灵活和易于维护。
如果您在阅读本文时获得了帮助或受到了启发,希望您能够喜欢并收藏这篇文章,为它点赞~
请在评论区与我分享您的想法和心得,一起交流学习,不断进步,遇见更加优秀的自己!