设计模式(长文解析)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在软件开发的世界中,设计模式如同一把钥匙,能够帮助开发者打开复杂问题的解决方案之门。无论是构建一个小型工具还是大型系统,设计模式都像是一套经过验证的“最佳实践”,帮助开发者更高效、更优雅地解决常见问题。本文将从基础概念出发,结合实际案例和代码示例,逐步揭开设计模式的神秘面纱,让编程初学者和中级开发者都能轻松理解并掌握这一重要工具。
什么是设计模式?
设计模式(Design Patterns)是针对特定问题的通用解决方案,它们总结了软件开发中反复出现的模式,并以标准化的形式呈现。这些模式并非具体的代码,而更像是解决问题的“模板”或“蓝图”。
比喻:
设计模式就像建筑中的“图纸”——建筑师不需要每次盖房子都重新设计屋顶或楼梯,而是可以参考已有的设计模板,快速完成结构搭建。
设计模式的核心价值在于:
- 提高代码复用性:减少重复劳动,提升开发效率;
- 增强系统可维护性:规范化的代码结构让团队协作更顺畅;
- 降低复杂性:将复杂问题分解为可管理的模块,降低理解难度。
设计模式的分类与核心思想
根据《设计模式:可复用面向对象软件的基础》(即“GoF”书),设计模式被分为三类:创建型、结构型、行为型。
创建型模式
这类模式关注对象的创建过程,通过隐藏对象的创建逻辑,降低系统耦合性。
1. 单例模式(Singleton Pattern)
定义:确保一个类仅有一个实例,并提供全局访问点。
使用场景:数据库连接、日志记录器等需要唯一实例的场景。
案例:
想象一个国家只能有一个总统,无论多少人尝试选举,最终只能选出唯一一人。
代码示例(Python):
class President:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
p1 = President()
p2 = President()
print(p1 == p2) # 输出:True
优缺点:
- 优点:严格控制实例数量,节省资源。
- 缺点:可能隐藏程序的复杂性,过度使用会导致代码难以调试。
2. 工厂模式(Factory Pattern)
定义:定义一个创建对象的接口,让子类决定实例化哪一个类。
使用场景:当对象创建逻辑复杂或需要动态选择类型时。
比喻:
快餐店的点餐系统——顾客选择汉堡或薯条,系统根据选择生成对应的餐品对象。
代码示例(Java):
// 抽象产品
interface Food {
void prepare();
}
// 具体产品
class Burger implements Food {
public void prepare() {
System.out.println("Preparing burger...");
}
}
// 工厂类
class FoodFactory {
public static Food createFood(String type) {
if ("burger".equals(type)) return new Burger();
// 其他类型...
return null;
}
}
// 使用
Food food = FoodFactory.createFood("burger");
food.prepare();
结构型模式
这类模式关注类与对象的组合方式,通过调整结构提升系统的灵活性和扩展性。
1. 适配器模式(Adapter Pattern)
定义:将一个类的接口转换为客户端期望的另一个接口,解决兼容性问题。
使用场景:旧系统与新接口对接、第三方库的适配等。
比喻:
充电器适配器——将不同国家的电压标准转换为设备可接受的电压。
代码示例(JavaScript):
// 目标接口
class Target {
request() {
return "Target works!";
}
}
// 需要适配的类
class Adaptee {
specificRequest() {
return "Adaptee's special method!";
}
}
// 适配器
class Adapter extends Target {
constructor(adaptee) {
super();
this.adaptee = adaptee;
}
request() {
return this.adaptee.specificRequest();
}
}
// 使用
const adaptee = new Adaptee();
const adapter = new Adapter(adaptee);
console.log(adapter.request()); // 输出:Adaptee's special method!
2. 代理模式(Proxy Pattern)
定义:为其他对象提供一种代理以控制对原对象的访问。
使用场景:网络资源加载、安全权限验证等。
案例:
电影票代理售票系统——用户通过代理购买电影票,代理先验证用户是否有资格购票(如年龄限制),再调用真实售票系统。
代码示例(C#):
// 真实主题
class RealTheater {
public void ShowMovie() {
Console.WriteLine("Movie is playing!");
}
}
// 代理
class ProxyTheater {
private RealTheater theater = new RealTheater();
private bool isValidUser = false;
public void ShowMovie() {
if (isValidUser) {
theater.ShowMovie();
} else {
Console.WriteLine("Access denied!");
}
}
}
// 客户端
var proxy = new ProxyTheater();
proxy.ShowMovie(); // 输出:Access denied!
行为型模式
这类模式关注对象之间的通信和职责分配,优化系统协作逻辑。
1. 观察者模式(Observer Pattern)
定义:定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖者自动收到通知。
使用场景:UI组件事件监听、订阅-发布系统等。
比喻:
社交媒体关注系统——用户关注某个账号后,会自动收到该账号的新动态通知。
代码示例(Python):
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def notify(self):
for observer in self._observers:
observer.update()
class Observer:
def update(self):
print("Received update!")
subject = Subject()
observer1 = Observer()
observer2 = Observer()
subject.attach(observer1)
subject.attach(observer2)
subject.notify() # 输出:Received update! ×2
2. 策略模式(Strategy Pattern)
定义:定义一系列算法,将它们封装起来,并使它们可互换。
使用场景:支付方式选择、排序算法切换等。
比喻:
快递公司根据包裹重量选择运输策略——轻包裹用无人机,重包裹用卡车。
代码示例(Java):
// 策略接口
interface ShippingStrategy {
double calculateCost(int weight);
}
// 具体策略
class DroneStrategy implements ShippingStrategy {
public double calculateCost(int weight) {
return 0.5 * weight;
}
}
// 上下文
class ShippingContext {
private ShippingStrategy strategy;
public void setStrategy(ShippingStrategy strategy) {
this.strategy = strategy;
}
public double calculateCost(int weight) {
return strategy.calculateCost(weight);
}
}
// 使用
ShippingContext context = new ShippingContext();
context.setStrategy(new DroneStrategy());
System.out.println(context.calculateCost(10)); // 输出:5.0
如何学习与应用设计模式?
1. 理解问题场景,而非死记硬背
设计模式的价值在于“解决问题”,而非强行套用。学习时应先理解模式背后的思想,再结合实际项目需求灵活应用。
2. 从简单模式开始实践
例如:
- 先尝试用单例模式管理数据库连接;
- 用观察者模式实现一个简单的事件监听系统。
3. 避免过度设计
设计模式并非万能钥匙,过度使用可能导致代码复杂度上升。例如,无意义地添加代理层反而会降低性能。
结论
设计模式是软件开发中不可或缺的“思维工具”,它们帮助开发者用更少的时间构建更健壮的系统。通过本文的讲解,读者可以初步掌握设计模式的核心分类、经典案例及应用技巧。
未来的学习中,建议结合具体项目实践,逐步深入理解模式的适用场景和变体形式。记住,设计模式是“为解决问题而生”,而非为炫技而用。只有真正理解其背后的设计哲学,才能让代码在简洁性、可维护性与扩展性之间找到最佳平衡点。
附录:设计模式速查表
类型 模式名称 主要用途 典型场景 创建型 单例模式 确保唯一实例 数据库连接、日志记录器 创建型 工厂模式 解耦对象创建逻辑 复杂对象初始化 结构型 适配器模式 转换接口兼容性 旧系统与新接口对接 结构型 代理模式 控制对对象的访问 网络资源加载、权限验证 行为型 观察者模式 实现一对多依赖通知 事件监听、订阅-发布系统 行为型 策略模式 封装可替换算法 支付方式选择、排序算法