设计模式(长文解析)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 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. 避免过度设计

设计模式并非万能钥匙,过度使用可能导致代码复杂度上升。例如,无意义地添加代理层反而会降低性能。


结论

设计模式是软件开发中不可或缺的“思维工具”,它们帮助开发者用更少的时间构建更健壮的系统。通过本文的讲解,读者可以初步掌握设计模式的核心分类、经典案例及应用技巧。

未来的学习中,建议结合具体项目实践,逐步深入理解模式的适用场景和变体形式。记住,设计模式是“为解决问题而生”,而非为炫技而用。只有真正理解其背后的设计哲学,才能让代码在简洁性、可维护性与扩展性之间找到最佳平衡点。


附录:设计模式速查表

类型模式名称主要用途典型场景
创建型单例模式确保唯一实例数据库连接、日志记录器
创建型工厂模式解耦对象创建逻辑复杂对象初始化
结构型适配器模式转换接口兼容性旧系统与新接口对接
结构型代理模式控制对对象的访问网络资源加载、权限验证
行为型观察者模式实现一对多依赖通知事件监听、订阅-发布系统
行为型策略模式封装可替换算法支付方式选择、排序算法

最新发布