设计模式 - 简单工厂模式
一、引入
假设你正在一个画图软件中工作,你可以用它来画各种形状,比如圆形和矩形。
-
不使用工厂模式:
- 客户端直接实例化了具体的圆形和矩形对象,依赖了具体的类。
- 客户端需要知道如何创建并使用这些对象。
-
使用简单工厂模式:
- 客户端只需要和工厂类交互,而不需要直接创建具体的形状对象。
- 工厂类负责根据客户端的请求来创建相应的形状对象。
二、概念
简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一个简单的工厂类来实例化对象,而不需要直接在客户端代码中创建对象。这个工厂类根据客户端的请求,决定创建哪种具体的对象。
三、基本结构
- 工厂类(SimpleFactory): 负责实例化具体的对象。它根据客户端的请求来决定创建哪种类型的对象,并返回相应的实例。
- 抽象产品类(Product): 定义了工厂类所创建的对象的接口或抽象类。通常会有多个具体产品类实现这个接口或继承这个抽象类。
- 具体产品类(ConcreteProduct): 实现了抽象产品类的接口或继承了抽象产品类,具体产品类是工厂类所创建的对象的具体实现。
四、示例代码
csharp
/**
* 形状接口
*
* @author zf
*/
public interface Shape {
void draw();
}
typescript
/**
* 具体的形状类 : 圆形
*
* @author zf
*/
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("圆形");
}
}
/**
* 具体的形状类 : 矩形
*
* @author zf
*/
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("矩形");
}
}
csharp
/**
* 形状工厂
*
* @author zf
*/
public class ShapeFactory {
public Shape getShape(String shapeType) {
if (Strings.isBlank(shapeType)) {
return null;
}
if ("CIRCLE".equals(shapeType)) {
return new Circle();
} else if ("RECTANGLE".equals(shapeType)) {
return new Rectangle();
}
return null;
}
}
typescript
/**
* 客户端
*
* @author zf
*/
public class Client {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
shapeFactory.getShape("CIRCLE").draw();
System.out.println("--------------------");
shapeFactory.getShape("RECTANGLE").draw();
}
}
运行结果 : 根据传入不同的参数,获得不同的产品
五、用途
简单工厂模式的常见用途包括但不限于以下几个方面:
- 对象的创建与使用分离: 简单工厂模式可以将对象的创建逻辑与客户端的使用逻辑分离,使得客户端代码更加简洁和清晰。
- 隐藏对象创建细节: 客户端不需要关心对象的具体创建过程,只需要向工厂类发出请求即可获得所需对象。
- 根据条件创建不同类型的对象: 工厂类可以根据不同的条件来创建不同类型的对象,提供了一定程度上的灵活性。
- 避免直接实例化具体类: 使用工厂模式可以避免客户端直接实例化具体的类,降低了客户端代码与具体类的耦合度。
工厂模式在日常开发中的一些涉及场景:
- 数据库连接池: 在开发中经常会使用数据库连接池来管理数据库连接对象,工厂模式可以用于创建和管理这些连接对象。
- 日志记录器的选择: 在日志记录功能中,可以使用工厂模式来选择合适的日志记录器,比如可以选择文件记录器或者数据库记录器。
- 支付方式选择: 在电商平台中,根据用户的选择可以使用工厂模式来创建不同的支付方式,比如支付宝、微信支付等。
- 配置解析器: 在系统中可能需要根据不同的配置文件类型(如XML、JSON等)来选择合适的配置解析器,工厂模式可以用于创建这些解析器对象。
六、总结
优点:
- 封装了对象的创建过程: 客户端代码不需要关心对象的创建细节,只需要向工厂类发送请求即可获得所需的对象。
- 降低了客户端和具体类的耦合度: 客户端只需要知道所需对象的名称或类型,而不需要直接依赖具体的类。
- 灵活性高: 可以根据客户端的请求,动态地决定创建哪种类型的对象,提供了一定程度上的灵活性。
- 可以隐藏对象创建细节: 工厂类可以处理对象的创建逻辑,客户端不需要关心具体的创建过程。
缺点:
- 违反了开闭原则: 如果需要添加新的产品类,就需要修改工厂类的代码,这违反了开闭原则(对扩展开放,对修改关闭)。
- 工厂类职责过重: 随着产品类的增多,工厂类可能会变得庞大而复杂,不利于代码的维护和管理。
- 不适用于复杂的对象创建逻辑: 如果对象的创建逻辑比较复杂,可能需要在工厂类中包含大量的逻辑判断,使得工厂类变得臃肿和难以维护。
- 可能引入不必要的依赖: 客户端需要知道具体产品的名称或类型,这可能会导致客户端和具体产品类之间的耦合,从而降低了代码的灵活性。
总的来说,简单工厂模式适用于对象的创建逻辑相对简单,客户端只需知道所需对象的名称或类型的情况。如果系统中涉及到多种产品类的创建,考虑使用工厂方法模式或抽象工厂模式,它们提供了更高级别的灵活性和扩展性。