设计模式讲座:C++中的单例、工厂与观察者模式
各位听众朋友们,欢迎来到今天的“设计模式”技术讲座!我是你们的讲师——代码老顽童。今天我们要探讨的是C++中的三大经典设计模式:单例(Singleton)、工厂(Factory)和观察者(Observer)。这些模式虽然听起来高深莫测,但其实就像日常生活中的小工具,用对了地方就能事半功倍。
为了让大家更好地理解,我会用通俗易懂的语言,并结合实际代码示例来讲解。别担心,不会有复杂的数学公式,也不会有晦涩难懂的术语。咱们轻松一点,愉快地学习!
第一讲:单例模式(Singleton Pattern)
什么是单例模式?
单例模式的核心思想是:一个类只能有一个实例,并且提供一个全局访问点。简单来说,就是让某个类在整个程序中只存在一个对象,无论你在哪里调用它,拿到的都是同一个对象。
举个生活中的例子:假设你是一家公司的CEO,你的秘书只有一个,不管谁想联系你,都得通过这个秘书。如果每个部门都去创建一个秘书,那岂不是乱套了?
在C++中实现单例模式非常简单。我们来看一段代码:
class Singleton {
private:
static Singleton* instance; // 静态指针,存储唯一实例
Singleton() {} // 私有构造函数,防止外部实例化
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton(); // 懒加载,首次调用时创建实例
}
return instance;
}
void showMessage() {
std::cout << "Hello from Singleton!" << std::endl;
}
};
// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
if (s1 == s2) {
std::cout << "s1 and s2 are the same instance!" << std::endl;
}
s1->showMessage();
return 0;
}
单例模式的优点与缺点
优点 | 缺点 |
---|---|
确保一个类只有一个实例 | 如果滥用,可能导致全局状态难以管理 |
提供全局访问点 | 不容易扩展为多实例 |
节省资源,避免重复创建对象 | 可能隐藏依赖关系,降低代码可测试性 |
第二讲:工厂模式(Factory Pattern)
什么是工厂模式?
工厂模式是一种创建型设计模式,它的核心思想是:将对象的创建过程封装起来,而不是直接使用new
关键字创建对象。这样做的好处是可以灵活地控制对象的创建逻辑,甚至可以在运行时动态决定创建哪种类型的对象。
想象一下,你去快餐店点汉堡。你只需要告诉服务员要点什么类型的汉堡(比如牛肉堡、鸡肉堡),而不需要自己动手做汉堡。这就是工厂模式的精髓!
在C++中,工厂模式通常分为简单工厂模式和抽象工厂模式。今天我们先看简单工厂模式的例子:
// 抽象产品类
class Burger {
public:
virtual void prepare() = 0; // 纯虚函数,定义接口
virtual ~Burger() {} // 虚析构函数,确保正确释放内存
};
// 具体产品类
class BeefBurger : public Burger {
public:
void prepare() override {
std::cout << "Preparing a beef burger..." << std::endl;
}
};
class ChickenBurger : public Burger {
public:
void prepare() override {
std::cout << "Preparing a chicken burger..." << std::endl;
}
};
// 工厂类
class BurgerFactory {
public:
static Burger* createBurger(const std::string& type) {
if (type == "beef") {
return new BeefBurger();
} else if (type == "chicken") {
return new ChickenBurger();
} else {
return nullptr;
}
}
};
int main() {
Burger* myBurger = BurgerFactory::createBurger("beef");
myBurger->prepare();
delete myBurger; // 别忘了释放内存哦!
return 0;
}
工厂模式的优点与缺点
优点 | 缺点 |
---|---|
将对象的创建与使用分离 | 增加了代码复杂度 |
支持开闭原则,易于扩展新类型 | 容易导致过多的工厂类 |
提高代码的灵活性 | 需要手动管理内存(C++中) |
第三讲:观察者模式(Observer Pattern)
什么是观察者模式?
观察者模式是一种行为型设计模式,它的核心思想是:定义对象间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会自动收到通知并更新。
举个例子,你订阅了一个新闻网站的推送服务。每当有新的新闻发布时,网站会自动通知你。你和其他订阅者之间没有直接联系,但你们都依赖于这个新闻网站。
在C++中实现观察者模式需要两个主要角色:被观察者(Subject) 和 观察者(Observer)。我们来看一个简单的例子:
#include <vector>
#include <iostream>
// 观察者接口
class Observer {
public:
virtual void update() = 0;
virtual ~Observer() {}
};
// 被观察者类
class Subject {
private:
std::vector<Observer*> observers; // 存储所有观察者
int state; // 当前状态
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 setState(int newState) {
state = newState;
notify(); // 状态变化时通知所有观察者
}
void notify() {
for (auto obs : observers) {
obs->update(); // 调用每个观察者的update方法
}
}
};
// 具体观察者
class ConcreteObserver : public Observer {
private:
std::string name;
public:
ConcreteObserver(const std::string& n) : name(n) {}
void update() override {
std::cout << name << " received notification!" << std::endl;
}
};
int main() {
Subject subject;
ConcreteObserver obs1("Alice"), obs2("Bob");
subject.attach(&obs1);
subject.attach(&obs2);
subject.setState(1); // 修改状态,触发通知
subject.detach(&obs1); // 移除观察者
subject.setState(2); // 再次修改状态,只有Bob收到通知
return 0;
}
观察者模式的优点与缺点
优点 | 缺点 |
---|---|
实现松耦合,观察者与被观察者独立 | 如果观察者过多,可能会导致性能问题 |
支持动态添加或移除观察者 | 通知顺序可能不可控 |
易于扩展新的观察者 | 过度使用可能导致系统复杂度增加 |
总结
今天的讲座就到这里啦!我们学习了三种经典的设计模式:单例模式、工厂模式和观察者模式。它们各自有不同的应用场景和优缺点,但共同的目标都是让我们的代码更加优雅、灵活和可维护。
希望这次讲座对你有所帮助!如果你有任何疑问或想法,欢迎在评论区留言。下次见啦,再见!