工厂方法模式详解
模式定义
工厂方法模式是创建型设计模式中的一种核心模式,它通过定义一个用于创建对象的抽象接口,让子类决定实例化哪一个具体的产品类。这种设计使得产品的创建过程延迟到子类中进行,从而实现了客户端代码与具体产品类的解耦。
该模式的核心思想是将对象的创建封装在专门的工厂类中,客户端只需要与抽象接口交互,无需关心具体的产品实现细节。这种设计符合软件设计中的开闭原则,即对扩展开放,对修改关闭。
模式结构
工厂方法模式主要由以下四个角色组成:
- 抽象产品(Product):定义产品的通用接口
- 具体产品(Concrete Product):实现抽象产品的具体类
- 抽象工厂(Creator):声明创建产品的抽象方法
- 具体工厂(Concrete Creator):重写抽象工厂方法以返回具体产品实例
代码实现
步骤一:定义抽象产品接口
public interface IMessage {
void display();
String getContent();
}
步骤二:创建具体产品实现类
public class TextMessage implements IMessage {
@Override
public void display() {
System.out.println("显示文本消息: " + getContent());
}
@Override
public String getContent() {
return "这是一条文本消息";
}
}
public class ImageMessage implements IMessage {
@Override
public void display() {
System.out.println("显示图片消息: " + getContent());
}
@Override
public String getContent() {
return "这是一张图片";
}
}
步骤三:定义抽象工厂
public abstract class MessageFactory {
public abstract IMessage createMessage();
public void showMessage() {
IMessage message = createMessage();
message.display();
}
}
步骤四:创建具体工厂类
public class TextMessageFactory extends MessageFactory {
@Override
public IMessage createMessage() {
return new TextMessage();
}
}
public class ImageMessageFactory extends MessageFactory {
@Override
public IMessage createMessage() {
return new ImageMessage();
}
}
步骤五:客户端使用
public class Client {
public static void main(String[] args) {
MessageFactory textFactory = new TextMessageFactory();
textFactory.showMessage();
MessageFactory imageFactory = new ImageMessageFactory();
imageFactory.showMessage();
}
}
执行结果
显示文本消息: 这是一条文本消息
显示图片消息: 这是一张图片
模式分析
在上述代码中,客户端代码与具体的产品类完全解耦。当需要添加新的消息类型时,只需要:
- 创建新的产品类实现
IMessage接口 - 创建对应的工厂类继承
MessageFactory
整个过程无需修改现有代码,完美体现了开闭原则的设计理念。
优势与不足
优势
- 用户只需知道具体工厂类名即可获取产品,无需了解创建细节
- 新增产品只需添加对应的工厂类,系统扩展性强
- 符合依赖倒置原则,高层模块依赖于抽象而非具体实现
- 实现客户端与具体产品的解耦,提高代码维护性
不足
- 类的数量会随着产品种类增加而增加
- 增加了系统的抽象层次,理解成本上升
- 每个抽象产品只能对应一个具体产品,当需要创建产品族时显得力不从心
适用场景
- 客户端不关心产品创建的具体过程
- 需要通过子类来决定创建何种产品对象 li>希望将产品创建逻辑集中管理,统一对外提供产品
- 系统需要频繁扩展新的产品类型
UML类图
工厂方法模式的UML类图结构清晰展示了各角色之间的关系:抽象工厂定义了创建产品的抽象方法,具体工厂负责实例化具体产品,抽象产品定义了产品的通用接口,具体产品实现了产品的具体功能。这种清晰的层次结构使得代码易于理解和维护。