工厂模式
工厂模式(Factory Pattern)是一种在软件工程中常用的创建型设计模式,它提供了一种创建对象的方式,同时隐藏创建逻辑,不是通过直接使用 new 运算符实例化对象。
工厂模式定义了一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
例子:
- 汽车制造:你需要一辆汽车,只需从工厂提货,而不需要关心汽车的制造过程及其内部实现。
- Hibernate:更换数据库时,只需更改方言(Dialect)和数据库驱动(Driver),即可实现对不同数据库的切换。
工厂模式包含以下几个主要角色:
- 抽象产品(Abstract Product):定义了产品的共同接口或抽象类。它可以是具体产品类的父类或接口,规定了产品对象的共同方法。
- 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
- 抽象工厂(Abstract Factory):声明了创建产品的抽象方法,可以是接口或抽象类。它可以有多个方法用于创建不同类型的产品。
- 具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象。
工厂方法模式流程:
-
定义产品接口:
- 创建一个产品接口,它定义了产品的公共方法。
-
创建具体产品类:
- 实现产品接口,创建多个具体产品类。
-
创建工厂类:
- 创建工厂,实现生产产品。
-
客户端使用:
- 客户端代码通过工厂接口来创建产品,无需知道具体产品类。
代码
package wnan.factory;
public interface Shape {
public abstract void draw();
}
package wnan.factory;
public class Circle implements Shape {
@Override
public void draw(){
System.out.println("Circle::show");
}
}
package wnan.factory;
public class Square implements Shape{
@Override
public void draw() {
System.out.println("Square::draw ");
}
}
package wnan.factory;
public class ShapeFactory {
public static Shape getShape(String shapeName) {
return switch (shapeName.toLowerCase()) {
case "circle" -> new Circle();
case "square" -> new Square();
default -> null;
};
}
}
package wnan.factory;
public class Client {
public static void main(String[] args) {
Shape circle = ShapeFactory.getShape("circle");
circle.draw();
Shape sqaure = ShapeFactory.getShape("square");
sqaure.draw();
}
}
分析
优点
- 调用者只需要知道对象的名称即可创建对象。
- 扩展性高,如果需要增加新产品,只需扩展一个工厂类即可。
- 屏蔽了产品的具体实现,调用者只关心产品的接口。
缺点
每次增加一个产品时,都需要增加一个具体类和对应的工厂,使系统中类的数量成倍增加,增加了系统的复杂度和具体类的依赖。
使用场景
- 日志记录:日志可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志的位置。
- 数据库访:当用户不知道最终系统使用哪种数据库,或者数据库可能变化时。
- 连接服务器的框架设计:需要支持 "POP3"、"IMAP"、"HTTP" 三种协议,可以将这三种协议作为产品类,共同实现一个接口。
注意事项
工厂模式适用于生成复杂对象的场景。如果对象较为简单,通过 new 即可完成创建,则不必使用工厂模式。使用工厂模式会引入一个工厂类,增加系统复杂度。