设计模式全局预览,以及为什么会

!设计模式的产生和发展背后有着深刻的原因:

一、为什么会有这么多设计模式?

1. 软件开发的普遍问题

  • 重复出现的问题:软件开发中很多问题是普遍存在的
  • 重复造轮子:程序员们反复解决相同的问题,但方法各异
  • 经验传承:将优秀解决方案标准化,避免重复探索

2. 模式的形成过程

java 复制代码
// 以单例模式为例:为什么需要它?
// 问题:如何确保一个类只有一个实例?

// 原始方案(各种不完善的尝试)
class Database {
    // 每个人都用自己的方式控制,容易出错
}

// 经过多年实践,提炼出的最佳方案
class SingletonDatabase {
    private static SingletonDatabase instance;
    
    private SingletonDatabase() {}  // 私有构造
    
    public static SingletonDatabase getInstance() {
        if (instance == null) {
            instance = new SingletonDatabase();
        }
        return instance;
    }
}

二、设计模式诞生的根本原因

1. 应对软件设计的复杂性

java 复制代码
// 没有模式的情况:代码紧密耦合
class OrderService {
    private MySQLDatabase db;  // 直接依赖具体实现
    private EmailSender email; // 紧密耦合
    
    public void createOrder() {
        // 业务逻辑、数据访问、发送邮件混在一起
    }
}

// 使用模式后:职责分离
class OrderService {
    private Database db;        // 依赖抽象(策略模式)
    private NotificationSender sender; // 依赖接口
    
    public void createOrder() {
        // 业务逻辑清晰
    }
}

2. 解决特定类型的问题

问题类型 解决方案模式 具体问题
对象创建复杂 建造者模式 创建包含多个部分的复杂对象
接口不兼容 适配器模式 新旧系统接口不一致
状态管理复杂 状态模式 对象行为随状态改变
对象依赖过多 观察者模式 多个对象需要监听一个对象的变化

三、设计模式解决的核心问题

1. 代码的可维护性

java 复制代码
// 问题:修改时牵一发而动全身
// 解决方案:使用模式降低耦合

// 坏示例:硬编码
class PaymentProcessor {
    public void pay(String type) {
        if ("credit".equals(type)) {
            // 信用卡支付逻辑
        } else if ("paypal".equals(type)) {
            // PayPal支付逻辑
        }
        // 新增支付方式需要修改这里
    }
}

// 好示例:策略模式
interface PaymentStrategy {
    void pay();
}

class PaymentProcessor {
    private PaymentStrategy strategy;  // 易于扩展
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
}

2. 代码的可扩展性

java 复制代码
// 问题:系统难以扩展新功能
// 解决方案:装饰器模式

// 基础组件
interface Coffee {
    double getCost();
    String getDescription();
}

// 装饰器基类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
}

// 可以轻松添加新功能而不修改原有类
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double getCost() {
        return decoratedCoffee.getCost() + 0.5;
    }
}

3. 代码的复用性

java 复制代码
// 模板方法模式:复用算法骨架
abstract class DataProcessor {
    // 模板方法
    public final void process() {
        readData();
        processData();  // 由子类实现
        saveData();
    }
    
    protected abstract void processData();
}

四、设计模式的演进过程

历史背景:

  1. 1970-80年代:面向对象编程兴起
  2. 常见问题反复出现:程序员们各自解决相似问题
  3. 1994年 GoF:Erich Gamma等4人总结23种模式
  4. 模式社区发展:不断发现和记录新模式

为什么模式会持续增加?

java 复制代码
// 新问题催生新模式
// 例如:响应式编程催生 Reactor 模式
// 并发编程催生 Actor 模式

五、重要设计模式诞生的原因

1. 单例模式:为什么出现?

  • 问题:全局资源(配置、数据库连接池)需要唯一实例
  • 防止:资源浪费、状态不一致
  • 示例:Spring的ApplicationContext

2. 观察者模式:为什么出现?

  • 问题:对象状态变化,多个对象需要知道
  • 传统方案:直接调用所有依赖对象(紧耦合)
  • 观察者模式:解耦,支持动态添加/移除观察者

3. 工厂模式:为什么出现?

  • 问题:对象创建逻辑复杂,可能变化
  • 坏处new ConcreteClass() 散布各处
  • 好处:创建逻辑集中,易于修改

六、现实世界的类比

建筑模式的启发

  • Christopher Alexander(建筑学家)首先提出"模式"概念
  • 建筑设计中的"门窗安排"、"房间布局"等模式
  • 软件设计借鉴了这一思想

生活中的模式

  • 餐厅点餐:模板方法模式(固定流程:点餐→烹饪→上菜→结账)
  • 电源适配器:适配器模式(不同插头标准转换)
  • 快递物流:责任链模式(快递经过多个中转站)

七、正确看待设计模式

不要过度使用

java 复制代码
// 反模式:为了模式而模式
class SimpleService {
    // 一个简单类不需要工厂+单例+装饰器...
}

// 正确的态度:按需使用
// 1. 先写简单直接的代码
// 2. 发现痛点(变化、扩展、维护问题)
// 3. 选择合适模式重构

模式的价值

  1. 沟通词汇:说"用观察者模式"比描述整个方案更高效
  2. 最佳实践总结:避免重复踩坑
  3. 设计思维训练:学习如何设计灵活、可维护的系统

总结

设计模式的产生是软件开发经验积累的必然结果 。它们不是凭空发明的,而是从无数实际项目中提炼出来的解决特定问题的成熟方案。就像木工的工具箱,不同的工具(模式)解决不同的问题。理解模式背后的"为什么"比记住模式本身更重要,这样才能在适当的时候选择适当的工具。

相关推荐
小股虫3 小时前
让系统“杀不死”:同步与异步场景下的弹性设计模式手册
分布式·微服务·设计模式·架构·团队建设·方法论
山风wind4 小时前
设计模式:状态模式详解-让对象的行为随状态改变而改变
设计模式·状态模式
__万波__4 小时前
二十三种设计模式(十八)--中介者模式
java·设计模式·中介者模式
自由生长202411 小时前
设计模式和设计原则-中高级架构思路-面向接口编程
设计模式
大厂技术总监下海1 天前
为何顶尖科技公司都依赖它?解码 Protocol Buffers 背后的高性能、可演进设计模式
分布式·设计模式
EnzoRay1 天前
代理模式
设计模式
weixin_478433321 天前
iluwatar 设计模式
java·开发语言·设计模式
郝学胜-神的一滴1 天前
Python面向对象编程:解耦、多态与魔法艺术
java·开发语言·c++·python·设计模式·软件工程
__万波__1 天前
二十三种设计模式(十六)--迭代器模式
java·设计模式·迭代器模式