1. 设计模式入门:为什么这8种模式值得优先掌握?
在C++开发领域摸爬滚打多年后,我发现一个有趣的现象:虽然GoF提出的设计模式有23种,但实际项目中80%的场景往往由少数几种模式主导。这就好比做菜时虽然调料有几十种,但真正每天必用的就那么几样。
1.1 设计模式的本质价值
设计模式不是用来炫技的编程花招,而是解决特定问题的经验总结。它们主要应对三类问题:
- 对象创建难题:如何优雅地创建复杂对象?比如单例确保全局唯一性,工厂解耦创建过程
- 结构组织难题:如何灵活组合对象?如装饰器动态添加功能,适配器解决接口不匹配
- 行为管理难题:如何高效处理对象间交互?如观察者实现事件通知,策略封装算法族
1.2 高频模式速览表
| 模式类型 | 高频模式 | 典型应用场景 | 解决的核心问题 |
|---|---|---|---|
| 创建型 | 单例、工厂、建造者 | 配置管理、插件系统、复杂对象构建 | 对象创建的控制与封装 |
| 结构型 | 适配器、装饰器、代理 | 接口兼容、功能扩展、访问控制 | 类与对象组合的灵活性 |
| 行为型 | 策略、观察者 | 算法切换、事件通知 | 对象间的高效交互与通信 |
1.3 学习路径建议
根据多年带新人的经验,我建议按这个顺序学习:
- 单例模式(理解全局状态管理)
- 工厂模式(掌握对象创建解耦)
- 策略模式(体会接口抽象威力)
- 观察者模式(理解松耦合设计)
- 适配器模式(学习接口转换技巧)
- 装饰器模式(掌握动态扩展方法)
- 代理模式(认识访问控制价值)
- 建造者模式(实践复杂对象构建)
关键提示:不要试图一次性掌握所有模式。建议每学完一个模式后,立即在简单项目中实践,比如用单例实现日志系统,用工厂模式创建不同的图形对象。
2. 单例模式:全局控制的艺术
2.1 典型应用场景分析
在最近参与的分布式系统中,我们使用单例模式管理Redis连接池。这样做的核心优势是:
- 避免重复创建连接导致的资源浪费
- 统一管理连接生命周期
- 全局可访问的入口简化调用
2.2 现代C++实现方案
cpp复制class RedisManager {
public:
static RedisManager& instance() {
static RedisManager inst;
return inst;
}
Connection getConnection() {
if (pool.empty()) {
expandPool(5); // 扩容连接池
}
return pool.acquire();
}
private:
RedisManager() { initPool(10); } // 初始10个连接
~RedisManager() { pool.clear(); }
ConnectionPool pool;
// 禁用拷贝
RedisManager(const RedisManager&) = delete;
RedisManager& operator=(const RedisManager&) = delete;
};
2.3 关键实现细节
- 静态局部变量:C++11保证线程安全
- 资源管理:构造函数初始化,析构函数清理
- 防拷贝:显式删除拷贝构造和赋值运算符
- 延迟加载:首次调用时才创建实例
2.4 实际应用中的陷阱
去年我们项目曾因不当使用单例导致严重问题:
- 多个单例相互依赖,初始化顺序不可控
- 单例持有大量资源,影响单元测试
- 在多DLL工程中产生多个实例
解决方案:
- 使用依赖注入控制初始化顺序
- 为单例添加重置接口便于测试
- 显式控制DLL边界上的实例化
3. 工厂模式:创建逻辑的解耦大师
3.1 模式变体对比
| 工厂类型 | 适用场景 | 复杂度 | 扩展性 |
|---|---|---|---|
| 简单工厂 | 创建逻辑简单,产品类型固定 | 低 | 差 |
| 工厂方法 | 需要支持新产品类型 | 中 | 好 |
| 抽象工厂 | 创建产品家族 | 高 | 较好 |
3.2 完整代码示例:插件系统实现
cpp复制// 抽象产品接口
class IPlugin {
public:
virtual ~IPlugin() = default;
virtual void execute() = 0;
};
// 具体产品
class ImagePlugin : public IPlugin {
public:
void execute() override {
cout << "Processing image..." << endl;
}
};
class AudioPlugin : public IPlugin {
public:
void execute() override {
cout << "Processing audio..." << endl;
}
};
// 工厂基类
class PluginFactory {
public:
virtual unique_ptr<IPlugin> create() = 0;
virtual ~PluginFactory() = default;
};
// 具体工厂
class ImagePluginFactory : public PluginFactory {
public:
unique_ptr<IPlugin> create() override {
return make_unique<ImagePlugin>();
}
};
class AudioPluginFactory : public PluginFactory {
public:
unique_ptr<IPlugin> create() override {
return make_unique<AudioPlugin>();
}
};
// 使用示例
void loadPlugin(PluginFactory& factory) {
auto plugin = factory.create();
plugin->execute();
}
3.3 注册机制的实现技巧
在大型系统中,我们通常使用注册表模式:
cpp复制class PluginManager {
public:
using Creator = function<unique_ptr<IPlugin>()>;
void registerCreator(const string& type, Creator creator) {
registry[type] = move(creator);
}
unique_ptr<IPlugin> create(const string& type) {
if (auto it = registry.find(type); it != registry.end()) {
return it->second();
}
throw runtime_error("Unknown plugin type");
}
private:
unordered_map<string, Creator> registry;
};
// 注册示例
PluginManager manager;
manager.registerCreator("image", [] { return make_unique<ImagePlugin>(); });
manager.registerCreator("audio", [] { return make_unique<AudioPlugin>(); });
4. 建造者模式:复杂对象的组装流水线
4.1 模式适用场景分析
在开发游戏角色系统时,我们使用建造者模式处理角色创建:
- 角色包含数十种属性(外观、技能、装备等)
- 不同职业的角色构建流程差异大
- 需要支持分步骤构建和预设配置
4.2 现代C++实现方案
cpp复制class GameCharacter {
public:
struct Attributes {
string race;
string profession;
int level = 1;
map<string, int> skills;
};
explicit GameCharacter(Attributes attrs) : attrs_(move(attrs)) {}
void show() const {
cout << "Race: " << attrs_.race
<< "\nProfession: " << attrs_.profession
<< "\nLevel: " << attrs_.level << endl;
}
private:
Attributes attrs_;
};
class CharacterBuilder {
public:
CharacterBuilder() = default;
CharacterBuilder& setRace(string race) {
attrs_.race = move(race);
return *this;
}
CharacterBuilder& setProfession(string profession) {
attrs_.profession = move(profession);
return *this;
}
CharacterBuilder& addSkill(string name, int level) {
attrs_.skills[move(name)] = level;
return *this;
}
GameCharacter build() {
return GameCharacter(move(attrs_));
}
private:
GameCharacter::Attributes attrs_;
};
// 使用示例
GameCharacter warrior = CharacterBuilder()
.setRace("Human")
.setProfession("Warrior")
.addSkill("Sword", 5)
.build();
4.3 与工厂模式的对比
| 特性 | 建造者模式 | 工厂模式 |
|---|---|---|
| 适用对象 | 复杂对象(多部件、多配置) | 标准对象 |
| 构建过程 | 分步骤、可定制 | 一步完成 |
| 关注点 | 对象构建的细节与顺序 | 对象创建的解耦 |
| 典型应用 | 配置对象、UI组件、文档生成 | 插件系统、驱动加载 |
5. 适配器模式:接口转换的桥梁
5.1 实际案例:旧日志系统改造
我们曾需要将遗留的C风格日志库接入现代C++系统:
cpp复制// 旧日志接口
extern "C" {
void legacy_log(const char* msg);
}
// 新日志接口
class ILogger {
public:
virtual ~ILogger() = default;
virtual void log(const string& msg) = 0;
};
// 适配器实现
class LegacyLoggerAdapter : public ILogger {
public:
void log(const string& msg) override {
legacy_log(msg.c_str());
}
};
// 使用示例
void process(ILogger& logger) {
logger.log("System started");
}
LegacyLoggerAdapter adapter;
process(adapter); // 无缝接入
5.2 适配器类型对比
| 类型 | 实现方式 | 适用场景 |
|---|---|---|
| 类适配器 | 多重继承 | 需要同时适配接口和实现 |
| 对象适配器 | 组合方式 | 更灵活,推荐首选 |
5.3 性能优化技巧
在金融系统开发中,我们发现适配器可能成为性能瓶颈:
- 避免深层嵌套:适配器链不超过3层
- 批量操作适配:为批量接口设计专用适配器
- 缓存适配结果:对不变的数据缓存转换结果
优化后的网络协议适配器示例:
cpp复制class ProtocolAdapter {
public:
explicit ProtocolAdapter(OldProtocol& old) : old_(old) {
cacheCommonHeaders();
}
NewMessage convert() {
if (cached) return cached.value();
NewMessage msg;
// 复杂转换逻辑...
cached = msg;
return msg;
}
private:
OldProtocol& old_;
optional<NewMessage> cached;
void cacheCommonHeaders() {
// 预缓存不变的数据
}
};
6. 装饰器模式:动态扩展的利器
6.1 实际应用:IO流增强
在文件处理系统中,我们通过装饰器叠加功能:
cpp复制class FileStream {
public:
virtual ~FileStream() = default;
virtual string read(int bytes) = 0;
virtual void write(const string& data) = 0;
};
// 基础实现
class BasicFileStream : public FileStream {
public:
string read(int bytes) override { /*...*/ }
void write(const string& data) override { /*...*/ }
};
// 装饰器基类
class FileStreamDecorator : public FileStream {
public:
explicit FileStreamDecorator(unique_ptr<FileStream> stream)
: stream_(move(stream)) {}
protected:
unique_ptr<FileStream> stream_;
};
// 具体装饰器:加密
class EncryptedStream : public FileStreamDecorator {
public:
using FileStreamDecorator::FileStreamDecorator;
string read(int bytes) override {
string data = stream_->read(bytes);
return decrypt(data);
}
void write(const string& data) override {
stream_->write(encrypt(data));
}
private:
string encrypt(const string& data) { /*...*/ }
string decrypt(const string& data) { /*...*/ }
};
// 使用示例
auto stream = make_unique<EncryptedStream>(
make_unique<BasicFileStream>("data.bin")
);
stream->write("secret"); // 自动加密
6.2 设计要点
- 保持接口一致性:装饰器必须实现原始接口的所有方法
- 透明性原则:使用者无需知道是否被装饰
- 避免过度装饰:装饰层数过多会影响性能和可维护性
6.3 与继承的对比
| 维度 | 装饰器模式 | 继承方案 |
|---|---|---|
| 扩展方式 | 运行时动态组合 | 编译时静态确定 |
| 灵活性 | 可任意组合功能 | 类爆炸问题 |
| 代码复杂度 | 单个装饰器简单 | 深层继承复杂 |
| 适用场景 | 需要动态添加/移除功能 | 功能组合固定不变 |
7. 代理模式:访问控制的守门人
7.1 代理类型全景图
| 代理类型 | 核心功能 | 典型应用场景 |
|---|---|---|
| 虚代理 | 延迟加载 | 大资源加载(如图片) |
| 保护代理 | 访问控制 | 权限管理系统 |
| 远程代理 | 本地代表远程对象 | RPC调用 |
| 智能引用 | 引用计数/自动清理 | 资源管理 |
| 缓存代理 | 结果缓存 | 计算密集型操作 |
7.2 智能指针实现示例
cpp复制template<typename T>
class SmartPointer {
public:
explicit SmartPointer(T* ptr) : ptr_(ptr), count_(new size_t(1)) {}
SmartPointer(const SmartPointer& other)
: ptr_(other.ptr_), count_(other.count_) {
++*count_;
}
~SmartPointer() {
if (--*count_ == 0) {
delete ptr_;
delete count_;
}
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
private:
T* ptr_;
size_t* count_;
};
7.3 性能敏感场景的优化
在高频交易系统中,我们发现代理可能引入额外开销。解决方案:
- 内联关键方法:对性能关键路径的方法使用inline
- 减少间接访问:缓存频繁访问的成员
- 使用轻量级代理:仅实现必要的接口方法
优化后的订单查询代理:
cpp复制class OrderQueryProxy : public IOrderQuery {
public:
explicit OrderQueryProxy(OrderService& service)
: service_(service) {}
Order getOrder(int id) override {
if (auto it = cache_.find(id); it != cache_.end()) {
return it->second;
}
Order order = service_.getOrder(id);
cache_[id] = order;
return order;
}
private:
OrderService& service_;
unordered_map<int, Order> cache_;
};
8. 策略模式:算法族的自由切换
8.1 电商折扣系统实战
cpp复制class DiscountStrategy {
public:
virtual ~DiscountStrategy() = default;
virtual double apply(double price) const = 0;
};
class NormalStrategy : public DiscountStrategy {
public:
double apply(double price) const override {
return price;
}
};
class VipStrategy : public DiscountStrategy {
public:
double apply(double price) const override {
return price * 0.9;
}
};
class PromotionStrategy : public DiscountStrategy {
public:
explicit PromotionStrategy(double discount)
: discount_(discount) {}
double apply(double price) const override {
return max(0.0, price - discount_);
}
private:
double discount_;
};
class Order {
public:
void setStrategy(unique_ptr<DiscountStrategy> strategy) {
strategy_ = move(strategy);
}
double checkout(double price) const {
return strategy_ ? strategy_->apply(price) : price;
}
private:
unique_ptr<DiscountStrategy> strategy_;
};
// 使用示例
Order order;
order.setStrategy(make_unique<VipStrategy>());
double finalPrice = order.checkout(100.0); // 90.0
8.2 策略注册表实现
cpp复制class StrategyFactory {
public:
using Creator = function<unique_ptr<DiscountStrategy>()>;
void registerStrategy(const string& name, Creator creator) {
creators_[name] = move(creator);
}
unique_ptr<DiscountStrategy> create(const string& name) const {
if (auto it = creators_.find(name); it != creators_.end()) {
return it->second();
}
throw invalid_argument("Unknown strategy");
}
private:
unordered_map<string, Creator> creators_;
};
// 注册策略
StrategyFactory factory;
factory.registerStrategy("vip", [] { return make_unique<VipStrategy>(); });
factory.registerStrategy("promo", [] {
return make_unique<PromotionStrategy>(50.0);
});
// 动态使用
auto strategy = factory.create("vip");
8.3 策略模式与状态模式对比
| 维度 | 策略模式 | 状态模式 |
|---|---|---|
| 目的 | 封装可互换的算法 | 封装与状态相关的行为 |
| 切换时机 | 客户端显式选择 | 对象内部状态自动触发 |
| 关注点 | 算法实现 | 状态转换逻辑 |
| 典型应用 | 支付方式、排序算法 | 工作流、游戏角色状态 |
9. 观察者模式:事件通知的优雅方案
9.1 股票行情系统实现
cpp复制class StockObserver {
public:
virtual ~StockObserver() = default;
virtual void update(const string& symbol, double price) = 0;
};
class StockMarket {
public:
void addObserver(shared_ptr<StockObserver> observer) {
observers_.push_back(observer);
}
void setPrice(const string& symbol, double price) {
priceMap_[symbol] = price;
notify(symbol, price);
}
private:
void notify(const string& symbol, double price) {
for (auto& observer : observers_) {
if (auto ptr = observer.lock()) {
ptr->update(symbol, price);
}
}
}
map<string, double> priceMap_;
vector<weak_ptr<StockObserver>> observers_;
};
class Trader : public StockObserver {
public:
void update(const string& symbol, double price) override {
cout << name_ << " received update: "
<< symbol << " = " << price << endl;
}
string name_;
};
// 使用示例
auto market = make_shared<StockMarket>();
auto trader1 = make_shared<Trader>();
trader1->name_ = "Alice";
market->addObserver(trader1);
market->setPrice("AAPL", 150.25); // Alice收到通知
9.2 性能优化策略
- 批量通知:收集多个变化后一次性通知
- 异步通知:使用线程池处理观察者回调
- 过滤通知:只有显著变化时才通知
- 弱引用观察者:避免观察者生命周期问题
优化后的实现:
cpp复制class EfficientNotifier {
public:
void addObserver(weak_ptr<StockObserver> observer) {
observers_.push_back(observer);
}
void queueUpdate(const string& symbol, double price) {
pendingUpdates_[symbol] = price;
if (shouldNotify()) {
flushNotifications();
}
}
private:
bool shouldNotify() const {
return pendingUpdates_.size() >= batchSize_ ||
chrono::steady_clock::now() - lastNotify_ > maxDelay_;
}
void flushNotifications() {
async(launch::async, [this] {
auto observers = observers_;
auto updates = move(pendingUpdates_);
for (const auto& [symbol, price] : updates) {
for (auto& weakObs : observers) {
if (auto obs = weakObs.lock()) {
obs->update(symbol, price);
}
}
}
});
lastNotify_ = chrono::steady_clock::now();
}
vector<weak_ptr<StockObserver>> observers_;
map<string, double> pendingUpdates_;
chrono::steady_clock::time_point lastNotify_;
size_t batchSize_ = 10;
chrono::milliseconds maxDelay_{500};
};
10. 设计模式组合应用实战
10.1 电商系统设计示例
结合多种模式实现灵活架构:
cpp复制// 使用工厂创建不同支付策略
class PaymentFactory {
public:
unique_ptr<PaymentStrategy> create(const string& type) {
if (type == "credit") return make_unique<CreditCardStrategy>();
if (type == "paypal") return make_unique<PayPalStrategy>();
throw invalid_argument("Unknown payment type");
}
};
// 使用建造者创建订单
class OrderBuilder {
public:
OrderBuilder& addItem(string id, int quantity) {
items_.emplace_back(move(id), quantity);
return *this;
}
Order build() {
return Order(move(items_));
}
private:
vector<pair<string, int>> items_;
};
// 使用观察者通知订单状态
class OrderNotifier {
public:
void addObserver(unique_ptr<OrderObserver> observer) {
observers_.push_back(move(observer));
}
void notifyCreated(const Order& order) {
for (auto& obs : observers_) {
obs->onOrderCreated(order);
}
}
private:
vector<unique_ptr<OrderObserver>> observers_;
};
// 组合使用
PaymentFactory paymentFactory;
auto payment = paymentFactory.create("credit");
Order order = OrderBuilder()
.addItem("1001", 2)
.addItem("2003", 1)
.build();
OrderNotifier notifier;
notifier.addObserver(make_unique<EmailNotifier>());
notifier.notifyCreated(order);
10.2 模式组合的最佳实践
- 工厂+策略:工厂创建不同的策略对象
- 建造者+单例:单例的建造者管理全局配置
- 观察者+代理:代理控制观察者的访问
- 装饰器+适配器:装饰适配后的对象
架构经验:模式组合时要保持单一职责原则,每个模式只解决一个特定问题。避免创建"超级模式"试图解决所有问题,这会导致系统过度复杂。
11. 设计模式在现代C++中的新表达
11.1 使用lambda简化策略模式
cpp复制class DiscountCalculator {
public:
using Strategy = function<double(double)>;
double calculate(double price, Strategy strategy) {
return strategy(price);
}
};
// 使用示例
DiscountCalculator calc;
double vipPrice = calc.calculate(100.0, [](double p) { return p * 0.9; });
double promoPrice = calc.calculate(100.0, [](double p) { return p - 20.0; });
11.2 使用std::variant实现访问者模式
cpp复制using DocumentItem = variant<Paragraph, Image, Table>;
class Document {
public:
void add(DocumentItem item) {
items_.push_back(move(item));
}
void render() const {
for (const auto& item : items_) {
visit([](const auto& elem) {
elem.render();
}, item);
}
}
private:
vector<DocumentItem> items_;
};
11.3 使用concept约束工厂产出
cpp复制template<typename T>
concept Plugin = requires(T t) {
{ t.execute() } -> same_as<void>;
};
class PluginFactory {
public:
template<Plugin P>
unique_ptr<P> create() {
return make_unique<P>();
}
};
12. 设计模式演进与趋势观察
12.1 模式使用频率变化
根据近五年代码库分析:
- 上升趋势:观察者、策略、工厂方法
- 下降趋势:单例(因测试困难)、模板方法
- 新兴组合:反应式编程+观察者、策略+lambda
12.2 现代C++特性对模式的影响
| 语言特性 | 简化的模式 | 影响程度 |
|---|---|---|
| lambda | 策略、命令 | 高 |
| smart pointer | 代理、享元 | 中 |
| variant/visit | 访问者 | 高 |
| concept | 工厂方法 | 中 |
12.3 架构层面的模式演进
-
微服务架构:
- 网关模式替代外观模式
- 服务发现替代抽象工厂
-
响应式系统:
- 数据流模式扩展观察者
- 背压控制引入新策略
-
云原生设计:
- 边车模式增强代理
- 算子模式重构策略
13. 设计模式的反模式与误用
13.1 常见误用案例
-
单例的滥用:
- 将本应是局部状态的对象设为单例
- 导致单元测试难以隔离
-
过度装饰:
- 创建过深的装饰器链(>5层)
- 导致调试困难
-
策略膨胀:
- 为微小差异创建过多策略类
- 增加维护成本
13.2 设计模式适用性检查清单
在决定使用模式前,先回答:
- 这个问题确实需要模式解决吗?
- 模式引入的复杂度是否值得?
- 是否有更简单的替代方案?
- 团队成员是否理解这个模式?
- 模式是否符合项目长期架构方向?
13.3 重构过度设计的策略
-
模式降级:
- 将抽象工厂改为工厂方法
- 将访问者改为variant访问
-
模式替换:
- 用策略替换状态模式
- 用组合替换装饰器
-
模式移除:
- 用简单回调替代观察者
- 用直接调用替代代理
14. 设计模式的测试策略
14.1 单例模式的测试技巧
cpp复制class Database {
public:
static Database& instance() {
static Database inst;
return inst;
}
// 测试专用重置方法
#ifdef TESTING
static void reset() {
instance().~Database();
new (&instance()) Database();
}
#endif
private:
Database() = default;
};
14.2 工厂模式的Mock测试
cpp复制struct IService {
virtual ~IService() = default;
virtual string getData() = 0;
};
class MockService : public IService {
public:
MOCK_METHOD(string, getData, (), (override));
};
TEST(ClientTest, UsesMockService) {
auto mock = make_shared<MockService>();
EXPECT_CALL(*mock, getData()).WillOnce(Return("test"));
Client client(mock);
ASSERT_EQ(client.process(), "test");
}
14.3 观察者模式的集成测试
cpp复制TEST(ObserverTest, NotifiesAllObservers) {
Subject subject;
MockObserver obs1, obs2;
EXPECT_CALL(obs1, update("msg")).Times(1);
EXPECT_CALL(obs2, update("msg")).Times(1);
subject.addObserver(&obs1);
subject.addObserver(&obs2);
subject.notify("msg");
}
15. 设计模式性能考量
15.1 运行时开销分析
| 模式 | 额外开销来源 | 典型开销范围 |
|---|---|---|
| 装饰器 | 虚函数调用链 | 5-15% |
| 代理 | 间接访问 | 3-8% |
| 观察者 | 通知遍历 | 可变 |
| 策略 | 虚函数调用 | 2-5% |
15.2 热点模式优化技巧
-
观察者模式:
- 使用分级通知
- 实现批量更新
-
装饰器模式:
- 扁平化装饰链
- 缓存装饰结果
-
策略模式:
- 使用std::function替代接口
- 模板策略避免虚调用
15.3 零开销抽象原则
通过编译期多态实现模式:
cpp复制template<typename Strategy>
class Context {
public:
explicit Context(Strategy s) : strategy_(s) {}
void execute() {
strategy_.run();
}
private:
Strategy strategy_;
};
struct FastStrategy {
void run() const { /* 高效实现 */ }
};
// 使用时无运行时开销
Context<FastStrategy> ctx(FastStrategy{});
ctx.execute();
16. 设计模式学习路线图
16.1 分阶段掌握计划
| 阶段 | 目标 | 建议时长 | 推荐模式 |
|---|---|---|---|
| 入门 | 理解基本概念 | 2周 | 单例、简单工厂、观察者 |
| 进阶 | 掌握组合应用 | 4周 | 策略、装饰器、建造者 |
| 精通 | 理解模式本质与变体 | 8周+ | 访问者、中介者、解释器 |
16.2 推荐学习资源
-
经典书籍:
- 《设计模式:可复用面向对象软件的基础》
- 《Head First设计模式》
- 《Modern C++ Design》
-
实践项目:
- 实现简易游戏引擎
- 构建插件系统
- 设计RPC框架
-
代码研究:
- STL中的迭代器模式
- Qt中的信号/槽(观察者)
- Boost中的策略模式应用
17. 设计模式面试精要
17.1 高频面试问题
-
单例模式:
- 如何实现线程安全?
- 如何避免静态初始化顺序问题?
-
工厂模式:
- 工厂方法与抽象工厂的区别?
- 如何支持运行时动态注册?
-
观察者模式:
- 如何处理观察者抛异常?
- 如何实现优先级通知?
17.2 问题回答框架
使用STAR法则:
- Situation:描述使用场景
- Task:需要解决的问题
- Action:模式的具体实现
- Result:达到的效果
17.3 代码评审要点
-
模式适用性:
- 是否确实需要该模式?
- 是否有更简单的方案?
-
实现质量:
- 是否遵循模式核心原则?
- 是否有潜在性能问题?
-
可测试性:
- 是否方便单元测试?
- Mock是否容易实现?
18. 设计模式与SOLID原则
18.1 单一职责原则(SRP)
- 装饰器模式:每个装饰器只添加一个功能
- 策略模式:每个策略只封装一个算法
18.2 开闭原则(OCP)
- 观察者模式:可扩展新观察者而不修改主题
- 策略模式:可添加新策略而不修改上下文
18.3 里氏替换原则(LSP)
- 工厂模式:产品对象可相互替换
- 策略模式:策略实现可相互替换
18.4 接口隔离原则(ISP)
- 适配器模式:创建特定客户端接口
- 代理模式:提供最小必要接口
18.5 依赖倒置原则(DIP)
- 工厂模式:依赖抽象而非具体类
- 策略模式:高层模块不依赖低层策略
19. 设计模式与架构风格
19.1 分层架构中的模式
- 外观模式:提供层级入口
- 中介者模式:协调层间通信
- 适配器模式:转换层间接口
19.2 微服务中的模式
- 代理模式:API网关实现
- 策略模式:服务选择策略
- 观察者模式:事件通知
19.3 事件驱动架构中的模式
- 观察者模式:事件发布/订阅
- 命令模式:事件对象封装
- 责任链模式:事件处理管道
20. 设计模式的未来展望
20.1 与新编程范式的融合
-
函数式编程:
- 策略模式→高阶函数
- 命令模式→闭包
-
响应式编程:
- 观察者模式→数据流
- 责任链模式→操作符链
20.2 与新兴技术的结合
-
AI代码生成:
- 自动识别模式应用场景
- 生成模式实现骨架
-
云原生环境:
- 服务网格中的代理模式
- 无函数中的策略模式
20.3 长期价值判断
-
持久价值:
- 解决核心设计问题的模式将长期存在
- 如观察者、策略、适配器
-
可能演进:
- 实现方式会随语言发展变化
- 但核心思想保持稳定
-
学习建议:
- 掌握思想而非具体实现
- 关注模式解决的问题域