https://www.bilibili.com/video/BV1Mb411t7ut的笔记
设计模式
核心的问题:如何同时提高一个软件系统的可维护性和可复用性
原则的目的:高内聚,低耦合
-
单一职责原则
类的职责单一,对外只提供一种功能,而引起类变化的原因应该只有一个
-
开闭原则
类的改动是通过代码进行的,而不是修改原代码
-
里氏代换原则
任何抽象类出现的地方都可以用他的实现类进行替换(多态)
-
依赖倒转原则
依赖于抽象,不要依赖与具体的实现,对接口编程
-
接口隔离原则
一个接口只提供一种对外的功能
-
合成复用原则
对于继承和组合,优先使用组合(即作为一个参数或者是一个内部成员)
-
迪米特原则
一个对象应当对其他对象尽可能少的了解,从而来降低偶和
简单工厂模式
通过一个工厂来创建要创建的类
好处:
- 客户端和具体实现类解耦
- 对于某些对象创建过程比较复杂的情况,我们也可以不去考虑(无需关心创建的过程)
不好:
- 简单工厂模式,增加新的功能是通过修改代码来实现的,不符合开闭原则
- 类的职责过重,若这个类发生问题,会影响很多使用这个工厂的模块
适用场景:
- 工厂类负责的对象比较少
- 客户端只知道传入工厂类的参数,对于如何创建对象不关心
案例
#include <iostream>
using namespace std;
class abstractFruit {
public:
virtual void showName() = 0;
};
class Apple : public abstractFruit {
public:
void showName() override {
cout << "i am apple" << endl;
}
};
class Banana : public abstractFruit {
public:
void showName() override {
cout << "i am Banana" << endl;
}
};
class FruitFactory {
public:
static abstractFruit* CreateFruit(string flag) {
if (flag == "apple") {
return new Apple;
} else {
return new Banana;
}
}
};
void test01() {
auto factory = new FruitFactory;
auto apple = factory->CreateFruit("apple");
auto banana = factory->CreateFruit("Banana");
apple->showName();
banana->showName();
}
int main() {
test01();
return 0;
}
工厂方法模式
将一个大的工厂抽象出来,然后每一个类都有一个对应的具体的工厂
缺点:
- 类的个数成倍增加(增加一个类,就要增加一个对应的工厂),从而导致类越来越多,增加了维护的成本
- 增加了系统的抽象性和理解难度
好处:
- 符合开闭原则
- 实现了对象创建和使用的分离
- 系统的可扩展性变得很好,无需修改接口和原类
使用场景:
- 客户端不知道他所需要的对象的类
- 抽象工厂类通过其子类来指定创建哪个对象
#include <iostream>
using namespace std;
class abstractFruit {
public:
virtual void showName() = 0;
};
class Apple : public abstractFruit {
public:
void showName() override {
cout << "i am apple" << endl;
}
};
class Banana : public abstractFruit {
public:
void showName() override {
cout << "i am Banana" << endl;
}
};
// 抽象工厂
class AbstractFactory {
public:
virtual abstractFruit* CreateFruit() = 0;
};
//苹果工厂
class AppleFactory : public AbstractFactory {
public :
abstractFruit* CreateFruit() override {
return new Apple;
}
};
//香蕉工厂
class BananaFactory : public AbstractFactory {
public :
abstractFruit* CreateFruit() override {
return new Banana;
}
};
void test01() {
AbstractFactory * factory = nullptr;
abstractFruit* fruit = nullptr;
factory = new AppleFactory;
fruit = factory->CreateFruit();
fruit->showName();
delete fruit;
delete factory;
factory = new BananaFactory;
fruit = factory->CreateFruit();
fruit->showName();
delete fruit;
delete factory;
}
int main() {
test01();
return 0;
}
抽象工厂模式
抽象工厂针对的是产品族,而不是产品的等级结构
-
产品族:同一产地或同一厂商,功能不同
-
产品等级:功能相同,产地或者厂商不同
#include <iostream>
using namespace std;
// 抽象苹果
class abstractApple {
public:
virtual void showName() = 0;
};
// 中国苹果
class chinaApple : public abstractApple {
public:
void showName() override {
cout << "中国苹果!" << endl;
}
};
// 日子苹果
class japApple : public abstractApple {
public:
void showName() override {
cout << "日子苹果!" << endl;
}
};
class abstractBanana {
public:
virtual void showName() = 0;
};
class chinaBanana : public abstractBanana {
public:
void showName() override {
cout << "中国香蕉!" << endl;
}
};
class japBanana : public abstractBanana {
public:
void showName() override {
cout << "日子香蕉!" << endl;
}
};
// 针对产品族
class abstractFactory {
public:
virtual abstractApple* CreateApple() = 0;
virtual abstractBanana* CreateBanana() = 0;
};
// 中国工厂
class chinaFactory : public abstractFactory {
public:
abstractApple* CreateApple() override {
return new chinaApple;
}
abstractBanana* CreateBanana() override {
return new chinaBanana;
}
};
// 日子工厂
class japFactory : public abstractFactory {
public:
abstractApple* CreateApple() override {
return new japApple;
}
abstractBanana* CreateBanana() override {
return new japBanana;
}
};
void test01() {
auto fac = new chinaFactory;
auto apple = fac -> CreateApple();
auto banana = fac -> CreateBanana();
apple->showName();
banana -> showName();
delete fac;
delete apple;
delete banana;
}
int main() {
test01();
return 0;
}
单例模式
单例模式只有一个实例, 并提供一个访问他的全局访问点
实现单例的步骤
- 构造函数私有化
- 增加静态私有的当前类的指针变量
- 提供一个静态的对外接口, 可以让用户获得单例对象
单例分为懒汉式和饿汉式
单例对象释放的问题
- 可以在对象中新建一个静态的 垃圾桶 ,通过 垃圾桶 的析构函数来释放单例对象
class singleton_hungry {
public:
static singleton_hungry* getInstance() {
return psingleton;
}
// 垃圾桶
class Garbo {
~Garbo() {
if (psingleton != nullptr)
delete psingleton;
}
};
private:
singleton_hungry() {
cout << "我是饿汉式!" << endl;
}
static singleton_hungry* psingleton;
static Garbo garbo;
};
多此一举!!!!因为当要销毁单例对象的时候,程序即将销毁,而当程序销毁的时候,单例对象自然会被销毁,所以无需手动销毁!!!!
代码演示
#include <iostream>
#include <algorithm>
using namespace std;
// 懒汉式-》只有当调用getInstance()的时候,才会new一个出来
class singleton_lazy {
public:
static singleton_lazy* getInstance() {
if (psingleton == nullptr) {
psingleton = new singleton_lazy;
}
return psingleton;
}
private:
singleton_lazy() {
cout << "我是懒汉式!" << endl;
}
static singleton_lazy* psingleton;
};
singleton_lazy* singleton_lazy::psingleton = nullptr;
// 饿汉式 -> 一开始就new一个
class singleton_hungry {
public:
static singleton_hungry* getInstance() {
return psingleton;
}
private:
singleton_hungry() {
cout << "我是饿汉式!" << endl;
}
static singleton_hungry* psingleton;
};
singleton_hungry* singleton_hungry::psingleton = new singleton_hungry;
// 查看懒汉式和饿汉式是不是一个单例
void test01() {
singleton_lazy* p1 = singleton_lazy::getInstance();
singleton_lazy* p2 = singleton_lazy::getInstance();
if (p1 == p2) {
cout << "两个指针指向同一个内存" << endl;
} else {
cout << "两个指针不指向同一个内存" << endl;
}
singleton_hungry* p3 = singleton_hungry::getInstance();
singleton_hungry* p4 = singleton_hungry::getInstance();
if (p3 == p4) {
cout << "两个指针指向同一个内存" << endl;
} else {
cout << "两个指针不指向同一个内存" << endl;
}
}
int main() {
cout << "main开始执行" << endl;
test01();
return 0;
}
单例模式遇到多线程
- 懒汉式是线程不安全的(可能同时new很多个对象)
- 饿汉式是线程安全的(对象在线程调用之前就已经创建好了)
代理模式
提供一种代理来控制对其他对象的访问
通过一个抽象类提供的一套相同的接口然后通过封装的方式,来实现通过对代理的访问来间接地访问真正的类。
#include <iostream>
using namespace std;
// 通过一种代理来控制对其他对象的访问
class abstractCommonInterface {
public:
virtual void run() = 0;
};
// 已经写好的系统
class MySystem : abstractCommonInterface{
public:
void run() override {
cout << "系统启动" << endl;
}
};
// 不是所有的人都可以启动系统,若要启动系统,则必须输入帐号和密码
class MySystemProxy : public abstractCommonInterface {
public:
MySystemProxy(string username, string password) {
this->mUsername = username;
this->mPassword = password;
pSystem = new MySystem;
}
void run() override {
if (checkUsernameAndPassword()) {
cout << "正确, 系统系统" << endl;
pSystem->run();
} else {
cout << "用户名或密码错误, 无法启动" << endl;
}
}
// 只读函数可以用const来确保这个函数不会修改数据
bool checkUsernameAndPassword() const {
if (mUsername == "root" && mPassword == "root")
return true;
return false;
}
~MySystemProxy() {
delete pSystem;
}
public:
//将系统作为一个成员,对系统做一个封装
MySystem* pSystem = nullptr;
string mUsername;
string mPassword;
};
void test01() {
auto proxy = new MySystemProxy("admin", "admin");
proxy->run();
delete proxy;
proxy = new MySystemProxy("root", "root");
proxy->run();
}
int main() {
test01();
return 0;
}
外观模式
外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
封装的内容可以是相互之间毫无关联的东西,但是是一个共同的功能下的。
#include <iostream>
using namespace std;
// 外观模式
// 电视机
class Tv {
public:
void On() {
cout << "电视机打开" << endl;
}
void off() {
cout << "电视机关闭" << endl;
}
};
// 灯
class Light {
public:
void On() {
cout << "灯打开" << endl;
}
void off() {
cout << "灯关闭" << endl;
}
};
// 音响
class Audio {
public:
void On() {
cout << "音响打开" << endl;
}
void off() {
cout << "音响关闭" << endl;
}
};
// 通过这个类可以yi jian
class CinemaMode {
public:
CinemaMode() {
pTv = new Tv;
pLight = new Light;
pAudio = new Audio;
}
void onCinema() {
pTv->On();
pLight->off();
pAudio->On();
}
void offCinema() {
pTv->off();
pLight->On();
pAudio->off();
}
~CinemaMode() {
delete pTv;
delete pLight;
delete pAudio;
}
Tv* pTv;
Light* pLight;
Audio* pAudio;
};
void test01() {
auto mode = new CinemaMode;
mode->onCinema();
cout << "//////////" << endl;
mode->offCinema();
delete mode;
}
int main() {
test01();
return 0;
}
适配器模式
在两个不兼容的接口之间搭建了一个桥梁,使得两个不同的接口可以使用。
代码实例
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 若直接将这个函数传递进去, 则会报错
struct myPrint{
void operator()(int v1, int v2) {
cout << v1 + v2 << endl;
}
};
// 定义目标接口:要适配成什么样子的。
class Target {
public:
virtual void operator()(int v) = 0;
};
// 写适配器
class Adapter : public Target {
public:
Adapter(int param) {
this->param = param;
}
void operator()(int v) override {
print(v, param);
}
myPrint print;
int param;
};
// MyBind2nd
Adapter MyBind2nd(int v) {
return Adapter(v);
}
int main() {
vector<int> v;
for (int i = 0; i < 10; i ++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), Adapter(10));
}
模板方法模式
一个抽象的类公开的定义了一个方法的模板。它的子类可以根据需要来重写这个方法,但调用将以抽象类中定义的方式进行。
好处:
- 父类形式化的定义一个算法,然后具体的实现的方法由子类来实现。
- 这是一种代码复用技术,他提取了类库中的公共行为,将公共行为放到父类中,然后其子类来实现各自不同的行为。
- 可以实现一种反向的控制,通过子类覆盖父类的函数,从而来防止某一步的执行。
- 符合单一职责原则和开闭原则。
代码实现
#include <iostream>
using namespace std;
class AbstractDrink {
public:
// 煮水
virtual void BoildWater() = 0;
// 冲泡
virtual void Brew() = 0;
// 倒入杯中
virtual void PourInTea() = 0;
// 加入辅料
virtual void AddSomeThing() = 0;
// 模板方法
void make() {
BoildWater();
Brew();
PourInTea();
AddSomeThing();
}
};
class Coffee : public AbstractDrink {
public:
// 煮水
void BoildWater() override {
cout << "烧水" << endl;
}
// 冲泡
void Brew() override {
cout << "冲泡" << endl;
}
// 倒入杯中
void PourInTea() override {
cout << "倒入杯中" << endl;
}
// 加入辅料
void AddSomeThing() override {
cout << "加入辅料" << endl;
}
};
class Tea : public AbstractDrink {
public:
// 煮水
void BoildWater() override {
cout << "烧茶" << endl;
}
// 冲泡
void Brew() override {
cout << "冲泡茶" << endl;
}
// 倒入杯中
void PourInTea() override {
cout << "倒入杯中" << endl;
}
// 加入辅料
void AddSomeThing() override {
cout << "加入辅料" << endl;
}
};
void test01() {
Tea a;
a.make();
cout << endl;
Coffee b;
b.make();
}
int main() {
test01();
return 0;
}
策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以相互替换。策略模式让算法独立于使用他的客户而独立变化。
代码示例
#include <iostream>
using namespace std;
// 抽象武器策略
class WeaponStrategy {
public:
virtual void UseWeapon() = 0;
};
class Knife : public WeaponStrategy {
public:
void UseWeapon() override {
cout << "使用了小刀" << endl;
}
};
class Ak : public WeaponStrategy {
public:
void UseWeapon() override {
cout << "使用了AK" << endl;
}
};
class Character {
public:
void setWeapon(WeaponStrategy* Weapon) {
this->pWeapon = Weapon;
}
void ThrowWeapon() {
this->pWeapon->UseWeapon();
}
WeaponStrategy* pWeapon;
};
void test01() {
// 创建角色
Character* character = new Character;
// 武器策略
WeaponStrategy* knife = new Knife;
WeaponStrategy* ak = new Ak;
character->setWeapon(knife);
character->ThrowWeapon();
character->setWeapon(ak);
character->ThrowWeapon();
delete character;
delete knife;
delete ak;
}
int main() {
test01();
return 0;
}
命令模式
将一个请求封装为一个对象, 从而可以用不同的请求对客户进行参数化。
好处:
- 命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求
- 可以实现函数的延时处理。
#include <unistd.h>
#include <iostream>
#include <queue>
using namespace std;
// 协议处理
class HandleClientProtocal {
public:
// 处理金币
void addMoney() {
cout << "给玩家增加金币!" << endl;
}
// 处理钻石
void addDiamond() {
cout << "给玩家增加钻石! " << endl;
}
// 处理装备
void addEquipment() {
cout << "给玩家穿装备! " << endl;
}
// 处理玩家升级
void addLevel() {
cout << "玩家升级了!" << endl;
}
};
// 命令接口
class AbstractCommond {
public:
virtual void handle() = 0;
};
class AddMoneyCommand : public AbstractCommond {
public:
AddMoneyCommand(HandleClientProtocal* protocal) {
this->pProtocal = protocal;
}
void handle() override {
this->pProtocal->addMoney();
}
HandleClientProtocal* pProtocal;
};
class AddDiamondCommand : public AbstractCommond {
public:
AddDiamondCommand(HandleClientProtocal* protocal) {
this->pProtocal = protocal;
}
void handle() override {
this->pProtocal->addDiamond();
}
HandleClientProtocal* pProtocal;
};
class AddEquipmentCommand : public AbstractCommond {
public:
AddEquipmentCommand(HandleClientProtocal* protocal) {
this->pProtocal = protocal;
}
void handle() override {
this->pProtocal->addEquipment();
}
HandleClientProtocal* pProtocal;
};
class AddLevelCommand : public AbstractCommond {
public:
AddLevelCommand(HandleClientProtocal* protocal) {
this->pProtocal = protocal;
}
void handle() override {
this->pProtocal->addLevel();
}
HandleClientProtocal* pProtocal;
};
// 服务器程序
class server {
public:
void addRequest(AbstractCommond* command) {
mCommands.push(command);
}
void startHandle() {
while (!mCommands.empty()) {
auto command = mCommands.front();
mCommands.pop();
command->handle();
sleep(1);
}
}
queue<AbstractCommond*> mCommands;
};
void test01() {
HandleClientProtocal* protocal = new HandleClientProtocal;
// 客户端增加金币
AbstractCommond* addmoney = new AddMoneyCommand(protocal);
// 客户端增加钻石
AbstractCommond* addDiamond = new AddDiamondCommand(protocal);
// 客户端穿装备
AbstractCommond* addEquipment = new AddEquipmentCommand(protocal);
// 客户端增加金币
AbstractCommond* addLevel = new AddLevelCommand(protocal);
server* ser = new server;
// 将客户端的请求发送到服务器中
ser->addRequest(addmoney);
ser->addRequest(addDiamond);
ser->addRequest(addEquipment);
ser->addRequest(addLevel);
// 服务器开始处理请求
ser->startHandle();
delete ser;
delete addmoney;
delete addDiamond;
delete addEquipment;
delete addLevel;
}
int main() {
test01();
return 0;
}
观察者模式
用于建立一种对象与对象之前的依赖关系, 一个对象发生改变的时候将自动通知其他的对象,其他对象将相应做出反应。发生改变的对象称为观察目标, 被通知的对象称为观察者。
#include <iostream>
#include <list>
using namespace std;
// 抽象的英雄
class AbstractHero {
public:
virtual void update() = 0;
};
class HeroA : public AbstractHero {
public:
HeroA() {
cout << "英雄A正在撸boss" << endl;
}
void update() override {
cout << "英雄A停止撸" << endl;
}
};
class HeroB : public AbstractHero {
public:
HeroB() {
cout << "英雄B正在撸boss" << endl;
}
void update() override {
cout << "英雄B停止撸" << endl;
}
};
class HeroC : public AbstractHero {
public:
HeroC() {
cout << "英雄C正在撸boss" << endl;
}
void update() override {
cout << "英雄C停止撸" << endl;
}
};
// 观察目标抽象
class AbstractBoss {
public:
virtual void addHero(AbstractHero* hero) = 0;
virtual void deleteHero(AbstractHero* hero) = 0;
virtual void notify() = 0; //通知观察者
};
class BossA : public AbstractBoss {
public:
void addHero(AbstractHero* hero) override {
pHeroList.push_back(hero);
}
void deleteHero(AbstractHero* hero) override {
pHeroList.remove(hero); //删除指定的人
}
void notify() override {
for (auto i : pHeroList) {
i->update();
}
}
private:
list<AbstractHero*> pHeroList;
};
void test01() {
// 创建观察者
HeroA heroA;
HeroB heroB;
HeroC heroC;
// 创建被观察者
BossA boss;
// 添加观察者
boss.addHero(&heroA);
boss.addHero(&heroB);
boss.addHero(&heroC);
boss.notify();
cout << "heroC阵亡" << endl;
boss.deleteHero(&heroC);
boss.notify();
}
int main() {
test01();
return 0;
}
装饰器模式
又叫包装模式,通过对客户端透明的方式来扩展对象功能。是继承关系的一种替代。
可以动态地给一个类拓展功能
#include <iostream>
using namespace std;
class AbstractHero {
public:
virtual void ShowStatus() = 0;
public:
int mHp;
int mMp;
int mAt;
int mDf;
};
class HeroA : public AbstractHero {
public:
HeroA() {
mHp = 0;
mMp = 0;
mAt = 0;
mDf = 0;
}
void ShowStatus() override {
cout << "血量" << mHp << endl;
cout << "魔法" << mMp << endl;
cout << "攻击" << mAt << endl;
cout << "防御" << mDf << endl;
}
};
// 英雄穿上装饰物
// 既有以前对象的功能, 又有新的对象的功能
class AbstractEquipment : public AbstractHero{
public:
AbstractEquipment(AbstractHero* hero) {
this->pHero = hero;
}
virtual void ShowStatus() {}
AbstractHero* pHero;
};
// 狂徒
class KuangtuEuqipment : public AbstractEquipment {
public:
// 继承基类
KuangtuEuqipment(AbstractHero* hero) : AbstractEquipment(hero) {
}
// 增加额外的功能
void addKuangtu() {
cout << "英雄穿上了狂徒披头" << endl;
this->mHp = this->pHero->mHp;
this->mMp = this->pHero->mMp;
this->mAt = this->pHero->mAt;
this->mDf = this->pHero->mDf + 30;
delete this->pHero;
}
virtual void ShowStatus() override {
addKuangtu();
cout << "血量" << mHp << endl;
cout << "魔法" << mMp << endl;
cout << "攻击" << mAt << endl;
cout << "防御" << mDf << endl;
}
};
// 刀
class knifeEquipment : public AbstractEquipment {
public:
// 继承基类
knifeEquipment(AbstractHero* hero) : AbstractEquipment(hero) {
}
// 增加额外的功能
void addKnifr() {
cout << "英雄拿起刀" << endl;
this->mHp = this->pHero->mHp;
this->mMp = this->pHero->mMp;
this->mAt = this->pHero->mAt + 30;
this->mDf = this->pHero->mDf;
delete this->pHero;
}
virtual void ShowStatus() override {
addKnifr();
cout << "血量" << mHp << endl;
cout << "魔法" << mMp << endl;
cout << "攻击" << mAt << endl;
cout << "防御" << mDf << endl;
}
};
void test01() {
AbstractHero* hero = new HeroA;
hero->ShowStatus();
cout << "----------" << endl;
// 给裸奔的有英雄穿衣服
hero = new KuangtuEuqipment(hero);
hero->ShowStatus();
cout << "-----------" << endl;
hero = new knifeEquipment(hero);
hero->ShowStatus();
};
int main() {
test01();
return 0;
}
1498

被折叠的 条评论
为什么被折叠?



