1. 单例模式 Singleton
适用场景
- 全局只需要一个对象
- 例如:日志系统、配置管理器、数据库连接池管理器、设备句柄管理器
你会怎么想到它
如果你脑子里出现:
- "全局唯一"
- "整个程序都要共享同一份状态"
- "不能重复创建,创建成本高"
大概率就会想到单例。
C++ 示例:日志管理器
cpp
#include <iostream>
#include <mutex>
#include <string>
class Logger {
public:
static Logger& instance() {
static Logger inst; // C++11 起线程安全
return inst;
}
void log(const std::string& msg) {
std::cout << "[LOG] " << msg << std::endl;
}
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
private:
Logger() = default;
};
int main() {
Logger::instance().log("Application started");
return 0;
}
识别关键词
- 全局唯一
- 共享状态
- 初始化一次
- 统一入口
2. 工厂方法模式 Factory Method
适用场景
- 你知道"要创建对象",但不想在业务代码里直接写
new具体类 - 让子类或工厂决定创建哪种对象
- 例如:创建不同类型的图形、不同类型的通知方式、不同类型的文档解析器
你会怎么想到它
如果需求是:
- "根据条件创建不同对象"
- "对象类型未来可能扩展"
- "调用方不关心具体类名"
那就很像工厂方法。
C++ 示例:创建不同通知对象
cpp
#include <iostream>
#include <memory>
#include <string>
FunWidgetFactory::FunWidgetFactory()
{
//创建几个常用的
}
IFunWidget *FunWidgetFactory::getFunWidget(IFunWidget::WidgetType type)
{
IFunWidget *pFunWidget = NULL;
enum WidgetType{
WGT_MAIN_MENU=0, //主界面
WGT_MEASURE, //
WGT_REVIEW, //数据界面
WGT_SETTING, //设置界面
WGT_SYS_CAL, //质控界面
WGT_SYS_INIT, //开机初始化
WGT_SHUTDOWN, //关机界面
WGT_INFO, //设备信息
WGT_TIME_DATE, //时间日期
WGT_SYSTEM_SET, //系统设置
WGT_REPORT_SET, //
WGT_PRINT_SET, //
WGT_COM_SET, //
WGT_TOUCH_CAL, //
WGT_DATA_MANAGE, //
WGT_Password, //
WGT_MAINTENANCE, //
WGT_LOCATING_SET, //
WGT_TEMP_SET, //
WGT_DA_SET, //
WGT_LED_SET, //
WGT_WIND_SW_TEST, //
WGT_ISN_SET, //
WGT_LED_ARG_SET, //
WGT_TEMP_ARG_SET, //
WGT_FAMHEX_CROSS_SET, //
WGT_OTHER_TEST_SET, //
WGT_SCREEN_TEST_SET, //
WGT_BUTUN_TEST_SET, //
WGT_AUTHORIZATION, //
WGT_AGENTMANAGE, //
WGT_SIGNAL_TEST, //
WGT_COOLING_CHECK, //
WGT_LED_TEST, //
WGT_LED_INIT, //
WidgetTypeMax
};
switch (type)
{
case IFunWidget::WGT_SYS_INIT:
{
qDebug() << "WGT_SYS_INIT";
pFunWidget = SystemInitWidget::GetInstance();
}
break;
case IFunWidget::WGT_MAIN_MENU:
{
qDebug() << "WGT_MAINMENU";
pFunWidget = MainManu::GetInstance();
}
break;
case IFunWidget::WGT_MEASURE:
{
qDebug() << "WGT_MEASURE";
pFunWidget = MeasureWidget::GetInstance();
}
break;
case IFunWidget::WGT_REVIEW:
{
qDebug() << "WGT_REVIEW";
pFunWidget = ReviewWidget::GetInstance();
}
break;
case IFunWidget::WGT_SETTING:
{
qDebug() << "WGT_SETTING";
pFunWidget = SettingWidget::GetInstance();
}
break;
case IFunWidget::WGT_INFO:
{
qDebug() << "WGT_INFO";
pFunWidget = DeviceInfoWidget::GetInstance();
}
break;
case IFunWidget::WGT_SHUTDOWN:
{
qDebug() << "WGT_SHUTDOWN";
pFunWidget = ShutdownWidget::GetInstance();
}
break;
case IFunWidget::WGT_TIME_DATE:
{
qDebug() << "WGT_DATE_SET";
pFunWidget = DateSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_REPORT_SET:
{
qDebug() << "WGT_REPORT_SET";
pFunWidget = ReportSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_COM_SET:
{
qDebug() << "WGT_COM_SET";
pFunWidget = CommunicationSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_MAINTENANCE:
{
qDebug() << "WGT_MAINTENANCE";
pFunWidget = MaintenanceWidget::GetInstance();
}
break;
case IFunWidget::WGT_PRINT_SET:
{
qDebug() << "WGT_PRINT_SET";
pFunWidget = PrintSettingWidget::GetInstance();
}
break;
case IFunWidget::WGT_TOUCH_CAL:
{
qDebug() << "WGT_TOUCH_CALIBRATION";
pFunWidget = TouchCalibrationWidget::GetInstance();
}
break;
case IFunWidget::WGT_DATA_MANAGE:
{
qDebug() << "WGT_DATA_MANAGE";
pFunWidget = DataManageWidget::GetInstance();
}
break;
case IFunWidget::WGT_SYSTEM_SET:
{
qDebug() << "WGT_SYSTEM_SET";
pFunWidget = SystemSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_Password:
{
qDebug() << "WGT_Password";
pFunWidget = PasswordWidget::GetInstance();
}
break;
case IFunWidget::WGT_LOCATING_SET:
{
qDebug() << "WGT_LOCATING_SET";
pFunWidget = LocalSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_DA_SET:
{
qDebug() << "WGT_DA_SET";
pFunWidget = DaSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_LED_SET:
{
qDebug() << "WGT_LED_SET";
pFunWidget = LedSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_WIND_SW_TEST:
{
qDebug() << "WGT_WIND_SW_TEST";
pFunWidget = WindTestWidget::GetInstance();
}
break;
case IFunWidget::WGT_ISN_SET:
{
qDebug() << "WGT_ISN_SET";
pFunWidget = ISNSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_TEMP_ARG_SET:
{
qDebug() << "WGT_TEMP_ARG_SET";
pFunWidget = TempArgSetWidget::GetInstance();
}
break;
case IFunWidget::WGT_OTHER_TEST_SET:
{
qDebug() << "WGT_OTHER_TEST_SET";
pFunWidget = OtherTest::GetInstance();
}
break;
case IFunWidget::WGT_SCREEN_TEST_SET:
{
qDebug() << "WGT_SCREEN_TEST_SET";
pFunWidget = ScreenTestWidget::GetInstance();
}
break;
case IFunWidget::WGT_BUTUN_TEST_SET:
{
qDebug() << "WGT_BUTUN_TEST_SET";
pFunWidget = ButtunTest::GetInstance();
}
break;
case IFunWidget::WGT_FAMHEX_CROSS_SET:
{
qDebug() << "WGT_FAMHEX_CROSS_SET";
pFunWidget = FamHexCrossSet::GetInstance();
}
break;
case IFunWidget::WGT_AUTHORIZATION:
{
qDebug() << "WGT_AUTHORIZATION";
pFunWidget = AuthorizationWidget::GetInstance();
}
break;
case IFunWidget::WGT_AGENTMANAGE:
{
qDebug() << "WGT_AGENTMANAGE";
pFunWidget = AgentManageWidget::GetInstance();
}
break;
case IFunWidget::WGT_SIGNAL_TEST:
{
qDebug() << "WGT_SIGNAL_TEST";
pFunWidget = SignalTest::GetInstance();
}
break;
case IFunWidget::WGT_COOLING_CHECK:
{
qDebug() << "WGT_COOLING_CHECK";
pFunWidget = CoolingTempCheck::GetInstance();
}
break;
case IFunWidget::WGT_LED_TEST:
{
qDebug() << "WGT_LED_TEST";
pFunWidget = LedTestWidget::GetInstance();
}
break;
case IFunWidget::WGT_LED_INIT:
{
qDebug() << "WGT_LED_INIT";
pFunWidget = LedInitDetec::GetInstance();
}
break;
default:
{
SHOW_DEBUG_INFO("default...");
}
break;
}
return pFunWidget;
}
int MainWindow()
{
...
this->switchFunctionWidgetSlot(IFunWidget::WGT_MEASURE);
...
}
识别关键词
- 创建对象
- 隐藏
new - 根据类型分派
- 扩展新产品
3. 观察者模式 Observer
适用场景
- 一个对象状态变化时,需要自动通知多个依赖对象
- 例如:消息订阅、GUI 事件、股票价格变化、传感器数据更新
你会怎么想到它
如果需求是:
- "一变多通知"
- "订阅/发布"
- "事件驱动"
- "监听某个变化"
那基本就是观察者。
C++ 示例:天气站通知多个显示器
cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
class Observer {
public:
virtual ~Observer() = default;
virtual void update(float temperature) = 0;
};
class Subject {
public:
void attach(Observer* obs) {
observers.push_back(obs);
}
void detach(Observer* obs) {
observers.erase(std::remove(observers.begin(), observers.end(), obs), observers.end());
}
void setTemperature(float temp) {
temperature = temp;
notify();
}
protected:
void notify() {
for (auto* obs : observers) {
obs->update(temperature);
}
}
private:
std::vector<Observer*> observers;
float temperature = 0.0f;
};
class PhoneDisplay : public Observer {
public:
void update(float temperature) override {
std::cout << "Phone display: " << temperature << " C" << std::endl;
}
};
class WindowDisplay : public Observer {
public:
void update(float temperature) override {
std::cout << "Window display: " << temperature << " C" << std::endl;
}
};
int main() {
Subject weather;
PhoneDisplay p;
WindowDisplay w;
weather.attach(&p);
weather.attach(&w);
weather.setTemperature(26.5f);
}
识别关键词
- 订阅
- 广播通知
- 事件回调
- 状态变化驱动多个对象更新
4. 策略模式 Strategy
适用场景
- 同一件事有多种算法/处理方式,需要可替换
- 例如:不同的排序算法、不同的支付方式、不同的压缩算法、不同的路径规划策略
你会怎么想到它
如果需求是:
- "同样目标,不同算法"
- "运行时可切换"
- "避免 if-else 一堆判断"
那通常就是策略模式。
C++ 示例:支付策略
cpp
#include <iostream>
#include <memory>
#include <string>
class PayStrategy {
public:
virtual ~PayStrategy() = default;
virtual void pay(int amount) = 0;
};
class AlipayStrategy : public PayStrategy {
public:
void pay(int amount) override {
std::cout << "Pay " << amount << " by Alipay" << std::endl;
}
};
class WechatPayStrategy : public PayStrategy {
public:
void pay(int amount) override {
std::cout << "Pay " << amount << " by WeChat Pay" << std::endl;
}
};
class PaymentContext {
public:
explicit PaymentContext(std::unique_ptr<PayStrategy> s)
: strategy(std::move(s)) {}
void checkout(int amount) {
strategy->pay(amount);
}
private:
std::unique_ptr<PayStrategy> strategy;
};
int main() {
PaymentContext c1(std::make_unique<AlipayStrategy>());
c1.checkout(100);
PaymentContext c2(std::make_unique<WechatPayStrategy>());
c2.checkout(200);
}
识别关键词
- 可替换算法
- 同一接口,不同行为
- 运行时切换
- 消灭大分支判断
5. 代理模式 Proxy
适用场景
- 你想通过一个"中间层"去控制真实对象
- 可能是延迟加载、访问控制、缓存、日志、远程调用
- 例如:图片懒加载代理、权限代理、远程服务代理
你会怎么想到它
如果需求是:
- "先别直接访问真实对象"
- "访问前后加点控制逻辑"
- "真实对象太重,先代理一下"
那就是代理。
C++ 示例:图片懒加载
cpp
#include <iostream>
#include <memory>
#include <string>
class Image {
public:
virtual ~Image() = default;
virtual void display() = 0;
};
class RealImage : public Image {
public:
explicit RealImage(const std::string& file) : filename(file) {
loadFromDisk();
}
void display() override {
std::cout << "Display " << filename << std::endl;
}
private:
void loadFromDisk() {
std::cout << "Loading " << filename << " from disk..." << std::endl;
}
std::string filename;
};
class ImageProxy : public Image {
public:
explicit ImageProxy(const std::string& file) : filename(file) {}
void display() override {
if (!realImage) {
realImage = std::make_unique<RealImage>(filename);
}
realImage->display();
}
private:
std::string filename;
std::unique_ptr<RealImage> realImage;
};
int main() {
ImageProxy img("photo.png");
std::cout << "Proxy created\n";
img.display(); // 第一次才加载
img.display(); // 直接显示
}
识别关键词
- 中间层
- 访问控制
- 延迟加载
- 缓存
- 远程对象
6. 装饰器模式 Decorator
适用场景
- 想在不修改原类的前提下,动态叠加功能
- 例如:给文本增加加粗/颜色、给流增加缓冲/压缩/加密、给订单增加优惠券/运费计算
你会怎么想到它
如果需求是:
- "在原功能基础上再加一层"
- "功能可组合"
- "不要用继承把类炸成很多组合"
那就很适合装饰器。
C++ 示例:咖啡加配料
cpp
#include <iostream>
#include <memory>
#include <string>
class Coffee {
public:
virtual ~Coffee() = default;
virtual std::string desc() const = 0;
virtual int cost() const = 0;
};
class SimpleCoffee : public Coffee {
public:
std::string desc() const override { return "Coffee"; }
int cost() const override { return 10; }
};
class CoffeeDecorator : public Coffee {
public:
explicit CoffeeDecorator(std::unique_ptr<Coffee> c)
: coffee(std::move(c)) {}
protected:
std::unique_ptr<Coffee> coffee;
};
class MilkDecorator : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
std::string desc() const override {
return coffee->desc() + " + Milk";
}
int cost() const override {
return coffee->cost() + 3;
}
};
class SugarDecorator : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
std::string desc() const override {
return coffee->desc() + " + Sugar";
}
int cost() const override {
return coffee->cost() + 1;
}
};
int main() {
std::unique_ptr<Coffee> coffee = std::make_unique<SimpleCoffee>();
coffee = std::make_unique<MilkDecorator>(std::move(coffee));
coffee = std::make_unique<SugarDecorator>(std::move(coffee));
std::cout << coffee->desc() << ", cost = " << coffee->cost() << std::endl;
}
识别关键词
- 动态叠加功能
- 包一层再加功能
- 组合多个增强行为
- 不想继承爆炸
快速记忆法:一句话区分
- Singleton:一个类只能有一个实例
- Factory Method:创建对象交给工厂
- Observer:一个变,多个跟着变
- Strategy:同一目标,不同算法可切换
- Proxy:找对象前先过一层"代理"
- Decorator:给对象"套外衣",功能层层叠加
你在项目里怎么快速判断
如果你看到这些需求,优先想到:
"全局唯一"
→ 单例
"创建哪种对象由条件决定"
→ 工厂方法
"一个对象状态变化要通知很多人"
→ 观察者
"同一个功能有多种实现,想动态切换"
→ 策略
"不直接访问真实对象,想加控制/懒加载"
→ 代理
"在不改原类的前提下叠加功能"
→ 装饰器
一个实际项目里的联想例子
假设你在做一个医疗设备软件:
- 日志系统:单例
- 根据设备型号创建不同采集器:工厂方法
- 传感器数据变化通知 UI、告警模块、记录模块:观察者
- 不同的报警阈值判定算法:策略
- 远程设备接口调用的缓存/权限控制层:代理
- 给数据流增加加密、压缩、校验:装饰器