第16讲:设计原则与设计模式的关系——原则是道,模式是术
这一讲,我想跟你聊聊一个很多人问过我的问题:设计原则和设计模式,到底什么关系?
我刚开始学设计模式那会儿,也犯过傻。背了二十多个模式,觉得挺牛。结果一到项目里,发现根本不知道用哪个。后来我才明白——光背模式没用,你得先懂原则。
打个比方吧。
原则是「道」,模式是「术」。
道是根本规律,术是具体招式。
你光练招式,不懂心法,那就是花架子。
核心观点:设计原则是设计模式的底层逻辑。每一个设计模式,都可以从某条或多条设计原则推导出来。反过来,如果你真正理解了原则,你甚至可以自己「发明」模式。
16.1 原则与模式:一个是根,一个是果
我们先看一张图,把关系理清楚。
你看,从上到下,是「道 → 术 → 用」的递进关系。
原则是抽象的,模式是具体的。模式是原则在特定场景下的「标准答案」。
16.2 从原则推导模式:一个例子就够了
我拿一个最常见的例子来说——策略模式。
假设你有一个订单系统。不同会员等级,折扣算法不一样。
新手可能会这么写:
class Order {
double calculateDiscount(string level) {
if (level == "普通") return price * 0.0;
else if (level == "银卡") return price * 0.1;
else if (level == "金卡") return price * 0.2;
// 再加一个等级?又得改这里
}
};
这代码有什么问题?
违反了开闭原则——对修改不关闭。每次加新等级,都得改这个函数。
好,那我们用原则来推导一下。
推导过程:
- 开闭原则告诉我们:对扩展开放,对修改关闭。所以不能改现有代码。
- 单一职责原则告诉我们:每个类只做一件事。折扣计算不应该和订单耦合在一起。
- 依赖倒置原则告诉我们:要依赖抽象,不要依赖具体实现。
三条原则一叠加,你自然就会想到:把折扣算法抽出来,做成一个接口,每个算法一个类。这不就是策略模式吗?
你看,我没背模式,我是从原则推导出来的。
// 策略接口
class DiscountStrategy {
public:
virtual double apply(double price) = 0;
};
// 具体策略
class NormalDiscount : public DiscountStrategy {
double apply(double price) override { return price; }
};
class SilverDiscount : public DiscountStrategy {
double apply(double price) override { return price * 0.9; }
};
// 订单类不再关心具体算法
class Order {
DiscountStrategy* strategy;
public:
void setStrategy(DiscountStrategy* s) { strategy = s; }
double calculate() { return strategy->apply(price); }
};
嗯,这才是面向对象该有的样子。
16.3 常见模式与原则的对应关系
我整理了一张表,方便你对照着看。
| 设计模式 | 核心遵循的原则 | 一句话解释 |
|---|---|---|
| 策略模式 | 开闭原则、依赖倒置 | 把算法抽出来,各自独立 |
| 工厂模式 | 依赖倒置、单一职责 | 把创建对象的责任单独拎出来 |
| 观察者模式 | 最少知识原则、开闭原则 | 发布者和订阅者互不依赖 |
| 装饰器模式 | 开闭原则、单一职责 | 不修改类,动态加功能 |
| 适配器模式 | 接口隔离原则、开闭原则 | 让不兼容的接口能一起工作 |
| 模板方法模式 | 里氏替换原则、开闭原则 | 固定骨架,子类填充细节 |
注意:一个模式往往对应多条原则。反过来,一条原则也可以推导出多个模式。这不是一一对应的关系,而是多对多的网状关系。
16.4 我踩过的坑:模式滥用
说实话,我早期也犯过「模式崇拜」的毛病。
有一次,一个简单的日志模块,我硬是套了工厂模式+单例模式+观察者模式。代码写了三百行,团队里没人看得懂。后来被架构师叫去谈话,他说了一句话我记到现在:「你是在写模式,不是在写代码。」
从那以后,我养成了一个习惯:
先问自己——这里违反了哪条原则?
如果没违反,就别硬上模式。
我的建议:
- 遇到设计问题,先想原则,再想模式
- 能用简单组合解决的,别用模式
- 模式是工具,不是目标
16.5 从原则推导模式的三步法
最后,我分享一个自己总结的方法。遇到设计问题时,按这三步走:
- 识别变化点——哪部分代码未来可能会变?
- 套用原则——哪条原则能解决这个变化?比如「开闭原则」要求封装变化。
- 匹配模式——这个封装方式,是不是正好对应某个模式?
举个例子:
变化点是「折扣算法经常新增」→ 开闭原则要求「对扩展开放」→ 策略模式正好封装算法族。
你看,三步走完,模式自然就出来了。
说白了,原则是心法,模式是招式。
心法通了,招式可以自己创。
心法不通,背再多招式也是花架子。
我个人更建议你把精力花在理解原则上。模式可以查,原则必须内化。
公众号:蓝海资料掘金营,微信 deep3321