设计模式实战:Spring中的模式应用
一、工厂模式:Spring就像一个大工厂
1.1 现实工厂类比
想象你去奶茶店点单: 你告诉店员要"珍珠奶茶"(getBean("pearlMilkTea")) 店员(Spring容器)根据配方制作奶茶 你不用关心奶茶是怎么做的
1.2 具体代码示例
// 定义产品接口
public interface MilkTea {
String getName();
}
// 具体产品
@Component("pearlMilkTea")
public class PearlMilkTea implements MilkTea {
public String getName() { return "珍珠奶茶"; }
}
// 在Controller中使用
@RestController
public class OrderController {
@Autowired // 自动从工厂获取
private MilkTea milkTea;
@GetMapping("/order")
public String order() {
return "你点的饮料是:" + milkTea.getName();
}
}
二、单例模式:节省资源的妙招
2.1 单例就像公司的打印机
全公司共用一台打印机(单例) 需要打印时去前台取用(getBean) 避免每个员工都买打印机(节省资源)
2.2 Spring单例示例
@Service // 默认就是单例
public class PrinterService {
private int printCount = 0;
public void print(String document) {
System.out.println("正在打印第" + (++printCount) + "份文件:" + document);
}
}
// 测试
@RestController
public class TestController {
@Autowired PrinterService printer1;
@Autowired PrinterService printer2;
@GetMapping("/test")
public String test() {
printer1.print("年度报告");
printer2.print("会议记录");
return "打印完成,printer1==printer2:" + (printer1 == printer2);
}
}
// 输出:true,说明是同一个实例
三、代理模式:AOP的魔法披风
3.1 代理就像明星的经纪人
你想联系明星(调用目标方法) 必须先通过经纪人(代理对象) 经纪人可以: 安排见面时间(前置增强) 记录谈话内容(后置增强) 拒绝不合理请求(权限控制)
3.2 Spring AOP实战
java
// 1. 定义切面(经纪人规则)
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeLog(JoinPoint jp) {
System.out.println("准备调用:" + jp.getSignature().getName());
}
}
// 2. 业务类(明星)
@Service
public class UserService {
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}
// 3. 测试
@RestController
public class UserController {
@Autowired UserService userService;
@GetMapping("/add")
public String addUser() {
userService.addUser("张三");
return "添加成功";
}
}
// 控制台输出:
// 准备调用:addUser
// 添加用户:张三
四、观察者模式:事件通知系统
4.1 就像微信订阅号
你关注了某个公众号(注册监听器) 公众号发布新文章(发布事件) 所有粉丝都会收到通知(通知监听器)
4.2 Spring事件示例
// 1. 定义事件(新文章)
public class NewArticleEvent extends ApplicationEvent {
private String title;
public NewArticleEvent(Object source, String title) {
super(source);
this.title = title;
}
public String getTitle() { return title; }
}
// 2. 发布者(公众号)
@Service
public class PublisherService {
@Autowired ApplicationEventPublisher publisher;
public void publishArticle(String title) {
System.out.println("发布新文章:" + title);
publisher.publishEvent(new NewArticleEvent(this, title));
}
}
// 3. 订阅者(粉丝)
@Component
public class Subscriber {
@EventListener
public void handleEvent(NewArticleEvent event) {
System.out.println("收到新文章通知:" + event.getTitle());
}
}
// 4. 测试
@RestController
public class TestController {
@Autowired PublisherService publisher;
@GetMapping("/publish")
public String publish() {
publisher.publishArticle("Spring设计模式详解");
return "发布成功";
}
}
// 控制台输出:
// 发布新文章:Spring设计模式详解
// 收到新文章通知:Spring设计模式详解
五、模板方法模式:流程固定,细节可变
5.1 就像泡茶的固定步骤
烧水(固定) 放茶叶(可变) 倒水(固定) 加料(可变) 搅拌(固定)
5.2 Spring JdbcTemplate示例
// 传统JDBC vs Spring模板方法
public class UserDao {
// 传统方式(需要自己处理所有步骤)
public User findUser(Long id) throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
stmt = conn.prepareStatement("SELECT * FROM users WHERE id=?");
stmt.setLong(1, id);
rs = stmt.executeQuery();
if (rs.next()) {
return new User(rs.getLong("id"), rs.getString("name"));
}
return null;
} finally {
// 需要手动关闭所有资源
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
}
// Spring模板方法方式(只需关注核心逻辑)
@Autowired JdbcTemplate jdbcTemplate;
public User findUserEasy(Long id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id=?",
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name")),
id);
}
}
六、设计模式记忆口诀
| 模式名称 | 口诀 | Spring应用示例 |
|---|---|---|
| 工厂模式 | "想要对象不用new,工厂里面拿就有" | BeanFactory |
| 单例模式 | "全局只用一实例,节省资源又省事" | @Service默认单例 |
| 代理模式 | "想要访问先过岗,代理帮你把事挡" | Spring AOP |
| 观察者 | "事件发生就通知,所有监听都知情" | ApplicationEvent |
| 模板方法 | "固定流程不变更,具体实现可调整" | JdbcTemplate |
七、常见问题解答
Q:为什么要用设计模式? A:就像建房子有标准施工流程:
- 使代码更规范(施工标准化)
- 更易维护(维修方便)
- 更易扩展(加层改造容易)
Q:Spring用了这么多模式,会不会很复杂? A:就像智能手机: 内部很复杂(各种芯片、传感器) 但用起来很简单(触摸屏操作) Spring也是这样,内部复杂但API简单 Q:怎么记住这些模式? A:多联系现实生活:
- 工厂模式 ≈ 奶茶店
- 单例模式 ≈ 公司打印机
- 代理模式 ≈ 明星经纪人
- 观察者 ≈ 微信订阅号
- 模板方法 ≈ 泡茶流程
记住:设计模式不是银弹,合适最重要!就像你不能用泡茶的流程去煮咖啡(虽然都是饮品),要根据实际需求选择合适的模式。