工厂模式和策略模式是两种不同的设计模式,它们分别解决的是创建对象和定义算法家族的问题。
工厂模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,它提供了一种创建对象的方式,使得创建对象的过程与使用对象的过程分离。
工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。
通过使用工厂模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。
应用实例
- 汽车制造:你需要一辆汽车,只需从工厂提货,而不需要关心汽车的制造过程及其内部实现。
- Hibernate:更换数据库时,只需更改方言(Dialect)和数据库驱动(Driver),即可实现对不同数据库的切换。
实现
我们将创建一个 Car接口和实现 Car 接口的实体类。然后定义工厂类 CarFactory。
- Car接口
public interface Car {
void run();
}
- 三个不同的Car实现类
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class AudiCar implements Car {
@Override
public void run() {
log.info("奥迪,启动!");
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BmwCar implements Car {
@Override
public void run() {
log.info("宝马,启动!");
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BydCar implements Car {
@Override
public void run() {
log.info("比亚迪,启动!");
}
}
- CarFactory
我们通过CarFactory的getCar方法来获取 Car 对象,然后通过统一的run方法来执行操作
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CarFactory {
/**
* 这里通过getCar获取不同的汽车对象
* @param name
* @return
*/
public Car getCar(String name) {
if (StrUtil.isNotBlank(name)) {
switch (name) {
case "比亚迪":
return new BydCar();
case "宝马":
return new BmwCar();
case "奥迪":
return new AudiCar();
}
}
throw new RuntimeException("类型获取失败!!");
}
public static void main(String[] args) {
CarFactory carFactory = new CarFactory();
Car car = carFactory.getCar("比亚迪");
car.run();
Car car2 = carFactory.getCar("宝马");
car2.run();
Car car3 = carFactory.getCar("奥迪");
car3.run();
Car car4 = carFactory.getCar("问界");
car4.run();
}
}
- 输出结果
策略模式
在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
应用实例
- 锦囊妙计:每个锦囊代表一个策略,包含不同的计策。
- 旅行方式选择:骑自行车、坐汽车等,每种方式都是一个可替换的策略。
- 消息通知:不同的消息通知,有不同的处理
实现
- 消息类和初始化类
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Message {
private String content;
private String type;
}
import java.util.ArrayList;
import java.util.List;
public class MessageBuilder {
public static List<Message> createTestMsg() {
List<Message> msgList = new ArrayList<Message>();
msgList.add(new Message("email消息通知测试","email"));
msgList.add(new Message("微信消息通知测试","wechat"));
msgList.add(new Message("QQ消息通知测试","qq"));
msgList.add(new Message("短信消息通知测试","msg"));
return msgList;
}
}
- 消息策略接口和实现类
public interface MessageStrategy {
void handleMsg(Message msg);
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class EmailStrategy implements MessageStrategy{
@Override
public void handleMsg(Message msg) {
log.info("收到email消息通知,正在解析内容:{}", msg.getContent());
log.info("执行email业务逻辑开始");
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MsgStrategy implements MessageStrategy{
@Override
public void handleMsg(Message msg) {
log.info("收到msg消息通知,正在解析内容:{}", msg.getContent());
log.info("执行msg业务逻辑开始");
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class QQStrategy implements MessageStrategy{
@Override
public void handleMsg(Message msg) {
log.info("收到qq消息通知,正在解析内容:{}", msg.getContent());
log.info("执行qq业务逻辑开始");
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class WechatStrategy implements MessageStrategy{
@Override
public void handleMsg(Message msg) {
log.info("收到wechat消息通知,正在解析内容:{}", msg.getContent());
log.info("执行wechat业务逻辑开始");
}
}
- 消息上下文对象和消息工厂
public class MessageContext {
private MessageStrategy messageStrategy;
public void setMessageStrategy(MessageStrategy messageStrategy) {
this.messageStrategy = messageStrategy;
}
public void handleMessage(Message message) {
if (message != null) {
messageStrategy.handleMsg(message);
}
}
}
import java.util.HashMap;
import java.util.Map;
public class MessageFactory {
private static Map<String, MessageStrategy> map = new HashMap<>();
public static void init() {
map.put("qq", new QQStrategy());
map.put("email", new EmailStrategy());
map.put("msg", new MsgStrategy());
map.put("wechat", new WechatStrategy());
}
public static MessageStrategy getMessageStrategy(String type){
return map.get(type);
}
}
- 执行的客户端类
import java.util.List;
public class StrategyClient {
public static void main(String[] args) {
List<Message> messages = MessageBuilder.createTestMsg();
MessageContext context = new MessageContext();
MessageFactory.init();
messages.forEach(temp -> {
MessageStrategy factory = MessageFactory.getMessageStrategy(temp.getType());
context.setMessageStrategy(factory);
context.handleMessage(temp);
});
}
}
- 执行结果
区别总结
-
应用场景:
工厂模式:用于创建对象,特别是当对象创建的逻辑很复杂或者需要根据条件创建不同类型的对象时。
策略模式:用于处理算法的选择和切换,特别是当这些算法是互斥的且可以在运行时改变时。 -
关注点:
- 工厂模式关注的是“如何创建对象”,强调的是创建过程的封装。
- 策略模式关注的是“如何使用算法”,强调的是算法的可替换性和独立性。