文章目录
ref
c++解决vscode cmd 输出中文乱码
system(“chcp 65001\n”); // Execute command line command chcp 65001
设计模式
- 创建型模式: 单例, 原型, 工厂方法, 抽象工厂, 建造者
- 隐藏了这些类的实例如何创建, 系统关于对象所知道的是由抽象类所定义的接口, 提供了灵活性
- 结构型模式: 代理, 适配器, 桥接, 装饰, 外观, 享元, 组合
- 行为型模式: 模板方法, 策略, 命令, 职责链, 状态, 观察者, 中介者, 迭代器, 访问者, 备忘录, 解释器
1. 简单工厂模式
- 不是GoF设计模式中正式的一员, 被认为是设计模式的起点
- 通过一个专门的类(工厂类)来创建产品对象, 客户端通过工厂类的静态/非静态方法传入参数, 工厂类根据参数决定创建什么产品
- 优点: 对象的创建和使用进行分离, 客户端无需关心具体产品实现, 只需知道产品接口
- 缺点: 增加新产品时需修改工厂类代码, 不符合开闭原则
#include <iostream>
#include <string>
using namespace std;
class Operation { // 运算基类
private:
double _numberA = 0;
double _numberB = 0;
public:
double GetA() { return _numberA; }
double GetB() { return _numberB; }
void SetA(double tmp) { _numberA = tmp; }
void SetB(double tmp) { _numberB = tmp; }
virtual double GetResult(){
double result = 0;
return result;
}
};
class OpAdd : public Operation { // 加法类
public:
double GetResult() override {
double result = GetA() + GetB();
return result;
}
};
class OpSub : public Operation { // 减法类
public:
double GetResult() override {
double result = GetA() - GetB();
return result;
}
};
class OpMul : public Operation { // 乘法类
public:
double GetResult() override {
double result = GetA() * GetB();
return result;
}
};
class OpDiv : public Operation { // 除法类
public:
double GetResult() override {
double result = GetB()==0 ? 0 : GetA() / GetB();
return result;
}
};
class OperationFactory{ // 运算工厂类
public:
static Operation* createOperate(char operate){
Operation* oper;
switch (operate)
{
case '+': oper = new OpAdd; break;
case '-': oper = new OpSub; break;
case '*': oper = new OpMul; break;
case '/': oper = new OpDiv; break;
default: break;
}
return oper;
}
};
int main()
{
Operation* oper = OperationFactory::createOperate('/');
oper->SetA(29);
oper->SetB(36);
cout << oper->GetResult();
}
2. 策略模式
- 定义一系列算法的方法, 以相同的方式调用所有算法(殊途同归), 减少各种算法类和使用算法类之间的耦合
- 优点
- 有助于析取这些算法的公共功能
- 简化了单元测试
#include<iostream>
using namespace std;
class CashSuper {
double _result;
public:
virtual double acceptCash(double money) {
double result = money;
return result;
}
};
class CashNormal : public CashSuper {
public:
double acceptCash(double money) override {
double result = money;
return result;
}
};
class CashRebate : public CashSuper { // 折扣策略
double _discount;
public:
CashRebate(double discount){
_discount = discount;
}
double acceptCash(double money) override {
double result = money*_discount;
return result;
}
};
class CashReturn : public CashSuper { // 满减策略
double _over;
double _sub;
public:
CashReturn(double over, double sub){
_over = over;
_sub = sub;
}
double acceptCash(double money) override {
double result = money>=_over?(money-_sub):money;
return result;
}
};
enum STRATEGY{
normal = 0,
over300sub100,
mul080
};
class CashContext {
CashSuper* _cs;
public:
CashContext(STRATEGY strategy){ // 传入具体收费策略
switch (strategy)
{
case normal:
_cs = new CashNormal();
break;
case over300sub100:
_cs = new CashReturn(300, 100);
break;
case mul080:
_cs = new CashRebate(0.8);
break;
default:break;
}
}
double GetResult(double money){
return _cs->acceptCash(money);
}
};
int main()
{
double total = 0.0f;
CashContext cashCount(over300sub100);
cout << cashCount.GetResult(800);
}
3. 单一职责原则
开放-封闭原则
- 对扩展开放, 对更改封闭
依赖倒转原则
- 高层模块不应该依赖低层模块, 两个都应该依赖抽象
- 抽象不应该依赖细节, 细节应该依赖抽象 ( 针对接口编程, 不对实现编程)
- 里氏代换原则: 软件不分辨父类对象和子类对象, 子类型必须能替换其父类型
6. 装饰模式
- 动态地给一个对象添加额外的职责
- 有效地把类的核心职责和装饰功能区分开, 去除重复装饰逻辑
#include<iostream>
#include<string>
using namespace std;
class Person{
private:
string _name;
public:
Person(){}
Person(string name){
this->_name = name;
}
~Person(){}
string Name(){
return this->_name;
}
virtual void Show(){
cout << _name << " 穿了" ;
}
};
class Finery : public Person{
protected:
Person* _component;
public:
void Decorate(Person* component){
_component = component;
}
void Show() override{
_component->Show();
}
};
class F_TShirt : public Finery{
public:
void Decorate(Person* component){
_component = component;
}
void Show() override{
_component->Show();
cout << " TShirt";
}
};
class F_BigTrouser : public Finery{
public:
void Decorate(Person* component){
_component = component;
}
void Show() override{
_component->Show();
cout << " 跨裤";
}
};
int main()
{
Person* ZiLu = new Person("子路");
F_TShirt* ts = new F_TShirt;
F_BigTrouser* bt = new F_BigTrouser;
ts->Decorate(ZiLu);
bt->Decorate(ts);
bt->Show();
delete ZiLu, ts, bt;
}
7. 代理模式
- 应用
- 远程代理: 为一个对象在不同地址空间提供局部代表, 隐藏它在不同地址空间的事实(vpn)
- 虚拟代理: 根据需要创建开销很大的对象, 通过其存放实例化需要长时间的真实对象(网页先加载文字后加载图片)
- 安全代理: 控制真实对象访问时的权限(对象应有不同访问权限)
- 智能指引: 调用真实对象时, 代理处理另外一些事
#include<iostream>
#include<string>
using namespace std;
class Girl{
string _name;
public:
Girl(string name) : _name(name) {}
};
// 实体和代理共用接口
class IGiveGift{
virtual void GiveGift(){}
};
// Proxy代表的真实实体
class Pursuit : public IGiveGift{
Girl* _pljj;
public:
Pursuit(Girl* pljj) : _pljj(pljj) {}
void GiveGift() override{
cout << "送礼1";
}
};
// 保存一个引用使代理可访问实体, 提供一个Subject接口相同的接口, 这样代理可替代实体
class Proxy : public IGiveGift{
Pursuit* _plgg;
public:
Proxy(Girl* pljj) {
_plgg = new Pursuit(pljj);
}
void GiveGift() override{
_plgg->GiveGift();
}
};
int main()
{
Girl* jiejie = new Girl("李姐");
Pursuit* tiangou = new Pursuit(jiejie);
tiangou->GiveGift();
Proxy* haoxiongdi = new Proxy(jiejie);
haoxiongdi->GiveGift();
}
8. 工厂方法模式
- 定义一个用于创建对象的接口, 让子类决定实例化哪个类
- 优点: 符合开闭原则, 新增产品只需添加新工厂类不修改已有代码
- 缺点: 客户端需要知道具体工厂类,
#include <iostream>
#include <string>
using namespace std;
class Operation { // 运算基类
private:
double _numberA = 0;
double _numberB = 0;
public:
double GetA() { return _numberA; }
double GetB() { return _numberB; }
void SetA(double tmp) { _numberA = tmp; }
void SetB(double tmp) { _numberB = tmp; }
virtual double GetResult(){
double result = 0;
return result;
}
};
class OpAdd : public Operation { // 加法类
public:
double GetResult() override {
double result = GetA() + GetB();
return result;
}
};
class OpSub : public Operation { // 减法类
public:
double GetResult() override {
double result = GetA() - GetB();
return result;
}
};
class OpMul : public Operation { // 乘法类
public:
double GetResult() override {
double result = GetA() * GetB();
return result;
}
};
class OpDiv : public Operation { // 除法类
public:
double GetResult() override {
double result = GetB()==0 ? 0 : GetA() / GetB();
return result;
}
};
class IFactory{ // 运算工厂类
public:
virtual Operation* createOperate(){
return nullptr;
}
};
class AddFactory : public IFactory{
public:
Operation* createOperate() override{
return new OpAdd;
}
};
class SubFactory : public IFactory{
public:
Operation* createOperate() override{
return new OpSub;
}
};
class MulFactory : public IFactory{
public:
Operation* createOperate() override{
return new OpMul;
}
};
class DivFactory : public IFactory{
public:
Operation* createOperate() override{
return new OpDiv;
}
};
int main()
{
IFactory* operFactory = new DivFactory();
Operation* oper = operFactory->createOperate();
oper->SetA(67.29);
oper->SetB(22);
cout << oper->GetResult();
}
9. 原型模式
- 用原型实例指定创建对象的种类, 通过拷贝这些原型创建新的对象
- (从一个对象再创建另一个可定制的对象, 且无需知道任何创建细节)
#include<iostream>
#include<string>
using namespace std;
typedef enum {
MAN = 0,
WOMAN = 1
}SEX;
class Resume{
string _name;
SEX _sex;
int _age;
public:
Resume(string name) : _name(name) {}
void SetInfo(SEX sex, int age){
_sex = sex;
_age = age;
}
void Show(){
cout << _name << ' ' << (_sex==0?"男":"女") << ' ' << _age << endl;
}
Resume* Clone(string name){
Resume* people = new Resume(name);
return people;
}
};
int main()
{
Resume* zhangsan = new Resume("张三");
zhangsan->SetInfo(MAN, 23);
zhangsan->Show();
Resume* lisi = zhangsan->Clone("李四");
lisi->SetInfo(WOMAN, 25);
lisi->Show();
}
10. 模板方法模式
- 将不变行为搬移到父类, 去除子类的重复代码
迪米特法则
- 最少知识原则: 如果两个类不必彼此通信, 两个类就不应发生直接的相互作用. 若一个类需调用另一个类某方法, 可通过第三者转发该调用
12. 外观模式
- 为子系统的一组接口提供一个一致的界面, 让其更容易使用
13. 建造者模式
- (生成器模式):将一个产品的内部表象与生成过程分开, 用户只需指定需要建造的类型, 无需知道具体建造过程和细节
- 应用: 创建一些复杂的对象, 这些对象内部构件建造顺序很稳定, 但对象内部构建常面临复杂的变化
#include<iostream>
#include<string>
using namespace std;
class Builder{
public:
virtual void BuildHead(){}
virtual void BuildBody(){}
virtual void BuildLegs(){}
};
class MkTall : public Builder{
public:
void BuildHead() override{
cout << "长型脸 ";
}
void BuildBody() override{
cout << "排骨 ";
}
void BuildLegs() override{
cout << "大长腿 ";
}
};
class MkShort : public Builder{
public:
void BuildHead() override{
cout << "方形脸 ";
}
void BuildBody() override{
cout << "96块腹肌 ";
}
void BuildLegs() override{
cout << "肌肉腿 ";
}
};
class Director{
public:
void Construct(Builder* builder){
builder->BuildHead();
builder->BuildBody();
builder->BuildLegs();
cout << endl;
}
};
int main()
{
MkTall* tall = new MkTall;
MkShort* shor = new MkShort;
Director leader;
leader.Construct(tall);
leader.Construct(shor);
}
14. 观察者模式
- 发布-订阅(Publish/Subscribe)模式, 定义了一种一对多的依赖关系, 让多个观察者同时监听某对象, 对象变化时通知所有观察者
- 特点: 解耦, subject改变, 所有Observer都得到通知
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
// void (*ptrMethod)();
class Observer;
class Notifier{
protected:
vector<Observer*> notDetect;
vector<Observer*> Detect;
public:
virtual void Notify() = 0;
};
class Observer{
protected:
string _name;
Notifier* _sub;
public:
Observer(string name, Notifier* sub) : _name(name),_sub(sub) {}
};
class ObsStock : public Observer{
public:
ObsStock(string name, Notifier* sub) : Observer(name, sub) {}
void UpdateGood(){
cout << this->_name << " 及时关掉广发证券, 继续debug\n";
}
void UpdateBad(){
cout << this->_name << " 没关掉广发证券, 扣钱\n";
}
};
class ObsGame : public Observer{
public:
ObsGame(string name, Notifier* sub) : Observer(name, sub) {}
void UpdateGood(){
cout << this->_name << " 及时关掉老头环, 继续debug\n";
}
void UpdateBad(){
cout << this->_name << " 没关掉老头环, 扣钱\n";
}
};
class Boss : public Notifier{
public:
vector<function<void()>> eventGood;
vector<function<void()>> eventBad;
void Notify(){
// myEvent();
for(auto it:eventGood){
it();
}
for(auto it:eventBad){
it();
}
}
};
int main()
{
Boss* LaoBan = new Boss;
ObsStock* ChaoGu = new ObsStock("韭菜", LaoBan);
ObsGame* DaJi = new ObsGame("彩笔", LaoBan);
LaoBan->eventGood.push_back(bind(&ObsStock::UpdateGood, ChaoGu));
LaoBan->eventGood.push_back(bind(&ObsGame::UpdateGood, DaJi));
LaoBan->eventBad.push_back(bind(&ObsStock::UpdateBad, ChaoGu));
LaoBan->eventBad.push_back(bind(&ObsGame::UpdateBad, DaJi));
LaoBan->Notify();
}
15. 抽象工厂模式
- 提供一个接口, 创建相关/依赖对象的家族, 无需明确指定具体类
- 优点: 一系列相关产品进行组合, 客户端无需关心具体工厂和产品, 降低客户端与具体实现的耦合
- 缺点: 难以支持新种类产品
- 没看完
16.状态模式
- 当一个对象内在状态改变时允许改变其行为, 看起来像改变了其类
- 当一个对象行为取决于其状态, 且必须在运行时刻根据状态改变行为时使用
- 优点: 将特定状态相关的行为局部化, 将不同状态的行为分隔开
#include <iostream>
class State;
class Work {
private:
State* current;
public:
Work();
double Hour;
bool TaskFinished;
void SetState(State* s);
void WriteProgram();
};
class State {
public:
virtual void WriteProgram(Work* w) = 0;
};
class ForenoonState : public State {
public:
void WriteProgram(Work* w) override;
};
class NoonState : public State {
public:
void WriteProgram(Work* w) override;
};
class AfternoonState : public State {
public:
void WriteProgram(Work* w) override;
};
class EveningState : public State {
public:
void WriteProgram(Work* w) override;
};
class SleepingState : public State {
public:
void WriteProgram(Work* w) override;
};
class RestState : public State {
public:
void WriteProgram(Work* w) override;
};
// Work 类的构造函数
Work::Work() {
current = new ForenoonState();
}
void Work::SetState(State* s) {
current = s;
}
void Work::WriteProgram() {
current->WriteProgram(this);
}
void ForenoonState::WriteProgram(Work* w) {
if (w->Hour < 12) {
std::cout << "当前时间:" << w->Hour << "点 上午工作,精神百倍" << std::endl;
} else {
w->SetState(new NoonState());
w->WriteProgram();
}
}
void NoonState::WriteProgram(Work* w) {
if (w->Hour < 13) {
std::cout << "当前时间:" << w->Hour << "点 饿了,午饭;犯困,午休。" << std::endl;
} else {
w->SetState(new AfternoonState());
w->WriteProgram();
}
}
void AfternoonState::WriteProgram(Work* w) {
if (w->Hour < 17) {
std::cout << "当前时间:" << w->Hour << "点 下午状态还不错,继续努力" << std::endl;
} else {
w->SetState(new EveningState());
w->WriteProgram();
}
}
void EveningState::WriteProgram(Work* w) {
if (w->TaskFinished) {
w->SetState(new RestState());
w->WriteProgram();
} else {
if (w->Hour < 21) {
std::cout << "当前时间:" << w->Hour << "点 加班哦,疲累之极" << std::endl;
} else {
w->SetState(new SleepingState());
w->WriteProgram();
}
}
}
void SleepingState::WriteProgram(Work* w) {
std::cout << "当前时间:" << w->Hour << "点 不行了,睡着了。" << std::endl;
}
void RestState::WriteProgram(Work* w) {
std::cout << "当前时间:" << w->Hour << "点 下班回家了" << std::endl;
}
int main() {
// 紧急项目
Work emergencyProjects;
emergencyProjects.Hour = 9;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 10;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 12;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 13;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 14;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 17;
// emergencyProjects.WorkFinished = true;
emergencyProjects.TaskFinished = false;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 19;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 22;
emergencyProjects.WriteProgram();
return 0;
}
17.适配器模式
- 将一个类的接口转换为客户希望的另一个接口, 解决接口兼容问题
#include <iostream>
#include <string>
using namespace std;
class Epeople {
protected:
string Name;
public:
Epeople(string name) : Name(name) {}
virtual void speak() = 0;
};
class Chinese{
protected:
string Ming;
public:
Chinese(string ming) : Ming(ming) {}
void shuo() {
cout << "朕是 " << Ming << endl;
}
};
class American : public Epeople {
public:
American(string name) : Epeople(name) {}
void speak() {
cout << "I am " << Name << endl;
}
};
class Translator : public Epeople {
Chinese* zhong = new Chinese(Name);
public:
Translator(string name) : Epeople(name) {}
void speak() {
zhong->shuo();
}
};
int main() {
American jack("Musk");
Translator fanyi("嬴政");
jack.speak();
fanyi.speak();
return 0;
}
18.备忘录模式
- 不破坏封装性前提下, 捕获一个对象内部状态, 在该对象外保存状态
- 适用于功能复杂但要维护/记录属性历史的类 / 保存属性只是众多属性小部分
#include<iostream>
#include<string>
using namespace std;
class StateMemento{
public:
int state1;
int state2;
int state3;
StateMemento(int s1,int s2, int s3){
this->state1 = s1;
this->state2 = s2;
this->state3 = s3;
}
};
class APP{
int state1;
int state2;
int state3;
public:
APP(int s1, int s2, int s3):state1(s1),state2(s2),state3(s3){}
void setState(int s1, int s2, int s3){
this->state1 = s1;
this->state2 = s2;
this->state3 = s3;
}
void stateDis(){
cout << "state:" << state1 << " " << state2 << " " << state3 << endl;
}
StateMemento* save(){
return (new StateMemento(state1, state2, state3));
}
void RecoveryState(StateMemento* memento){
this->state1 = memento->state1;
this->state2 = memento->state2;
this->state3 = memento->state3;
}
};
class StateMan{
public:
StateMemento* memento;
StateMan(){}
};
int main(){
APP app(1,2,3);
app.stateDis();
StateMan* man = new StateMan();
man->memento = app.save();
app.setState(4,5,6);
app.stateDis();
app.RecoveryState(man->memento);
app.stateDis();
}
19.组合模式
- 将对象组合成树形结构表示部分-整体的层次结构, 用户对单个对象和组合对象的使用有一致性
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Company{
protected:
public:
string _name;
Company(string name):_name(name){}
virtual void add(Company *c) = 0;
virtual void remove(Company *c) = 0;
virtual void display(int depth) = 0;
virtual void lineOfDuty() = 0;
};
class ConcreteCompany:public Company{
private:
vector<Company*>* _children;
public:
ConcreteCompany(string name):Company(name){
_children = new vector<Company*>();
}
void add(Company *c){
_children->push_back(c);
}
void remove(Company *c){
for(auto it = _children->begin(); it != _children->end(); it++){
if((*it)->_name == c->_name){
_children->erase(it);
break;
}
}
}
void display(int depth){
for(int i = 0; i < depth; i++){
cout << "-";
}
cout << _name << endl;
for(auto it = _children->begin(); it != _children->end(); it++){
(*it)->display(depth + 2);
}
}
void lineOfDuty(){
for(auto it = _children->begin(); it != _children->end(); it++){
(*it)->lineOfDuty();
}
}
};
class HRDepartment:public Company{
public:
HRDepartment(string name):Company(name){}
void add(Company *c){}
void remove(Company *c){}
void display(int depth){
for(int i = 0; i < depth; i++){
cout << "-";
}
cout << _name << endl;
}
void lineOfDuty(){
cout << _name << "员工招聘培训管理" << endl;
}
};
class FinanceDepartment:public Company{
public:
FinanceDepartment(string name):Company(name){}
void add(Company *c){}
void remove(Company *c){}
void display(int depth){
for(int i = 0; i < depth; i++){
cout << "-";
}
cout << _name << endl;
}
void lineOfDuty(){
cout << _name << "公司财务收支管理" << endl;
}
};
int main(){
system("chcp 65001\n"); // Execute command line command chcp 65001
ConcreteCompany *root = new ConcreteCompany("北京总公司");
root->add(new HRDepartment("总公司人力资源部"));
root->add(new FinanceDepartment("总公司财务部"));
ConcreteCompany *comp = new ConcreteCompany("上海华东分公司");
comp->add(new HRDepartment("华东分公司人力资源部"));
comp->add(new FinanceDepartment("华东分公司财务部"));
root->add(comp);
ConcreteCompany *comp1 = new ConcreteCompany("南京办事处");
comp1->add(new HRDepartment("南京办事处人力资源部"));
comp1->add(new FinanceDepartment("南京办事处财务部"));
comp->add(comp1);
ConcreteCompany *comp2 = new ConcreteCompany("杭州办事处");
comp2->add(new HRDepartment("杭州办事处人力资源部"));
comp2->add(new FinanceDepartment("杭州办事处财务部"));
comp->add(comp2);
cout << "结构图:" << endl;
root->display(1);
cout << "职责:" << endl;
root->lineOfDuty();
return 0;
}
20.迭代器模式
- 提供一种方法顺序访问一个聚合对象的各个元素, 不暴露对象的内部表示
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Iterator {
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() = 0;
virtual string CurrentItem() = 0;
};
class Aggregate {
public:
virtual Iterator* CreateIterator() = 0;
};
class ConcreteAggregate : public Aggregate {
private:
vector<string> m_vecItems;
public:
Iterator* CreateIterator();
int Count() {
return m_vecItems.size();
}
string GetItem(int idx) {
return m_vecItems[idx];
}
void SetItem(int idx, string str) {
m_vecItems[idx] = str;
}
void PushItem(string str) {
m_vecItems.push_back(str);
}
};
class ConcreteIterator : public Iterator {
private:
ConcreteAggregate* m_pAggregate;
int current = 0;
public:
ConcreteIterator(ConcreteAggregate* pAggregate) {
m_pAggregate = pAggregate;
}
void First() override {
current = 0;
}
void Next() override {
if (current < m_pAggregate->Count())
current++;
}
bool IsDone() override {
return current >= m_pAggregate->Count();
}
string CurrentItem() override {
return m_pAggregate->GetItem(current);
}
};
Iterator* ConcreteAggregate::CreateIterator() {
return new ConcreteIterator(this);
}
int main()
{
ConcreteAggregate* pAggregate = new ConcreteAggregate();
pAggregate->PushItem("A");
pAggregate->PushItem("B");
pAggregate->PushItem("C");
pAggregate->PushItem("D");
pAggregate->PushItem("E");
Iterator* pIterator = pAggregate->CreateIterator();
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
cout << pIterator->CurrentItem() << endl;
}
delete pAggregate;
delete pIterator;
cout << " ConcreteAggregate:" << sizeof(ConcreteAggregate) << " ConcreteIterator:" << sizeof(ConcreteIterator) << endl;
return 0;
}
21.单例模式
- 保证一个类仅有一个实例, 提供一个访问它的全局访问点. 构造方法私有化
#include<iostream>
#include<string>
using namespace std;
class Singleton {
private:
static Singleton* instance;
Singleton() {}
public:
static Singleton* GetInstance() {
if (instance == nullptr) {
instance = new Singleton();
cout << "instance created" << endl;
} else {
cout << "instance already exists" << endl;
}
return instance;
}
static void DeleteInstance() {
delete instance;
instance = nullptr;
cout << "instance deleted" << endl;
}
};
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* s1 = Singleton::GetInstance();
s1->DeleteInstance();
Singleton* s2 = Singleton::GetInstance();
return 0;
}
22.桥接模式
- 将抽象部分与其实现部分分离, 使其都可以独立变化(实现系统可能有多角度分类, 每种分类都可能变化, 将这种多角度分离让其独立变化, 减少耦合)
合成/聚合复用原则: 尽量用合成/聚合,尽量不用继承 - 优点: 助于每个类被封装, 集中在单个任务上, 类和类层次会保持较小规模, 不会过度增长
#include<iostream>
#include<string>
using namespace std;
class HandsetSoft {
public:
virtual void Run() = 0;
};
class HandsetGame : public HandsetSoft {
public:
void Run() override {
cout << "Run game" << endl;
}
};
class HandsetAddressList : public HandsetSoft {
public:
void Run() override {
cout << "Run address list" << endl;
}
};
class HandsetBrand {
protected:
HandsetSoft* soft;
public:
void SetHandsetSoft(HandsetSoft* soft) {
this->soft = soft;
}
virtual void Run() = 0;
};
class HandsetBrandN : public HandsetBrand {
public:
void Run() override {
soft->Run();
}
};
class HandsetBrandM : public HandsetBrand {
public:
void Run() override {
soft->Run();
}
};
int main(){
HandsetBrand* ab = new HandsetBrandN();
ab->SetHandsetSoft(new HandsetGame());
ab->SetHandsetSoft(new HandsetAddressList());
ab->Run();
return 0;
}
23.命令模式
- 将一个请求封装为一个对象, 从而使可用不同请求对客户进行参数化: 对请求排队/请求日志/支持可撤销的操作
- 优点: 分离请求操作的对象与执行操作的对象
- 容易设计命令队列
- 容易记入日志
- 允许接受请求一方决定是否否决请求
- 容易实现请求撤销和重做
- 容易新增具体命令类
#include<iostream>
#include<string>
using namespace std;
class Barbecuer {
public:
void BakeMutton() {
cout << "Bake mutton" << endl;
}
void BakeChickenWing() {
cout << "Bake chicken wing" << endl;
}
};
class Command {
protected:
Barbecuer* receiver;
Command(Barbecuer* receiver) {
this->receiver = receiver;
}
public:
virtual void ExecuteCommand() = 0;
};
class BakeMuttonCommand : public Command {
public:
BakeMuttonCommand(Barbecuer* receiver) : Command(receiver) {}
void ExecuteCommand() override {
receiver->BakeMutton();
}
};
class BakeChickenWingCommand : public Command {
public:
BakeChickenWingCommand(Barbecuer* receiver) : Command(receiver) {}
void ExecuteCommand() override {
receiver->BakeChickenWing();
}
};
class Waiter {
private:
Command* command;
public:
void SetCommand(Command* command) {
this->command = command;
}
void Notify() {
command->ExecuteCommand();
}
};
int main() {
Barbecuer* boy = new Barbecuer();
Command* bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command* bakeMuttonCommand2 = new BakeMuttonCommand(boy);
Command* bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
Waiter* girl = new Waiter();
girl->SetCommand(bakeMuttonCommand1);
girl->Notify();
girl->SetCommand(bakeMuttonCommand2);
girl->Notify();
girl->SetCommand(bakeChickenWingCommand1);
girl->Notify();
return 0;
}
24.职责链模式
- 使多个对象都有机会处理请求, 避免请求的发送者和接收者的耦合关系. 将该对象连成一条链, 沿该链传递请求, 直到有对象处理它
- 优点:
- 接收者和发送者都没有对方的明确信息, 链中对象不清楚链的结构, 简化对象的相互连接, 降低耦合
#include<iostream>
#include<string>
using namespace std;
class Request{
public:
string requestType;
string requestContent;
int number;
};
class Manager{
protected:
string _name;
Manager* _superior;
public:
Manager(string name):_name(name){}
void SetSuperior(Manager* superior){
_superior = superior;
}
virtual void RequestApplications(Request* request) = 0;
};
class CommonManager:public Manager{
public:
CommonManager(string name):Manager(name){}
void RequestApplications(Request* request){
if(request->requestType == "请假" && request->number <= 2) {
cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
} else {
if(_superior != NULL) {
_superior->RequestApplications(request);
}
}
}
};
class Majordomo:public Manager{
public:
Majordomo(string name):Manager(name){}
void RequestApplications(Request* request){
if(request->requestType == "请假" && request->number <= 5) {
cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
} else {
if(_superior != NULL) {
_superior->RequestApplications(request);
}
}
}
};
class GeneralManager:public Manager{
public:
GeneralManager(string name):Manager(name){}
void RequestApplications(Request* request){
if(request->requestType == "请假" && request->number <= 5) {
cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
} else if(request->requestType == "加薪" && request->number <= 500) {
cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
} else if(request->requestType == "加薪" && request->number > 500) {
cout << _name << ":" << request->requestContent << "数量" << request->number << "再说吧" << endl;
}
}
};
int main()
{
system("chcp 65001\n"); // Execute command line command chcp 65001
Manager* common = new CommonManager("经理");
Manager* majordomo = new Majordomo("总监");
Manager* general = new GeneralManager("总经理");
common->SetSuperior(majordomo);
majordomo->SetSuperior(general);
Request* request = new Request();
request->requestType = "请假";
request->requestContent = "小菜请假";
request->number = 1;
common->RequestApplications(request);
request->requestType = "请假";
request->requestContent = "小菜请假";
request->number = 4;
common->RequestApplications(request);
request->requestType = "加薪";
request->requestContent = "小菜请求加薪";
request->number = 500;
common->RequestApplications(request);
request->requestType = "加薪";
request->requestContent = "小菜请求加薪";
request->number = 1000;
common->RequestApplications(request);
return 0;
}
25.中介者模式 Mediator
- (调停者模式) 用一个中介对象来封装一系列的对象交互, 让对象无需显式相互引用, 耦合松散, 可独立改变其之间交互
- 通常应用于一组对象以定义良好但复杂的方式进行通信的场合
- 优点:
- 容易在系统中应用
- 缺点:
- 中介类最复杂
- 中介类最复杂
#include<iostream>
#include<string>
using namespace std;
class UniteNations;
class Country {
protected:
UniteNations* _mediator;
public:
Country(UniteNations* mediator):_mediator(mediator){}
};
class UniteNations {
public:
virtual void Declare(string message, Country* country) = 0;
};
class USA:public Country {
public:
USA(UniteNations* mediator):Country(mediator){}
void Declare(string message){
_mediator->Declare(message, this);
}
void GetMessage(string message){
cout << "USA获得对方信息:" << message << endl;
}
};
class Iraq:public Country {
public:
Iraq(UniteNations* mediator):Country(mediator){}
void Declare(string message){
_mediator->Declare(message, this);
}
void GetMessage(string message){
cout << "Iraq获得对方信息:" << message << endl;
}
};
class UniteNationsSecurityCouncil:public UniteNations {
private:
USA* _usa;
Iraq* _iraq;
public:
void SetUSA(USA* usa){
_usa = usa;
}
void SetIraq(Iraq* iraq){
_iraq = iraq;
}
void Declare(string message, Country* country){
if(country == _usa){
_iraq->GetMessage(message);
} else if(country == _iraq){
_usa->GetMessage(message);
}
}
};
int main () {
system("chcp 65001\n"); // Execute command line command chcp 65001
UniteNationsSecurityCouncil* UNSC = new UniteNationsSecurityCouncil();
USA* usa = new USA(UNSC);
Iraq* iraq = new Iraq(UNSC);
UNSC->SetUSA(usa);
UNSC->SetIraq(iraq);
usa->Declare("不准研制核武器,否则要发动战争!");
iraq->Declare("我们没有核武器,也不怕侵略。");
return 0;
}
26.享元模式 Flyweight
- 用共享技术有效支持大量细粒度对象, 避免大量类似的开销
- 在程序设计中, 有时需要生成大量细粒度的类实例表示数据, 如果能发现这些实例除了几个参数外基本相同, 则将不同的参数移到类实例的外面, 在方法调用时传递进来, 就可以通过共享大幅度减少单个实例的数目
- 内部状态: 在享元对象内部且不随环境改变而改变的共享部分
- 外部状态: 随环境改变而改变的, 不可以共享的状态
- 使用场景:
- 若一个应用使用了大量对象, 这些对象造成了很大的内存开销时考虑使用;
- 对象大多数状态可以外部状态, 删除外部状态可用较少的共享对象取代多组对象
#include<iostream>
#include<string>
#include<map>
using namespace std;
class User {
private:
string _name;
public:
User(string name):_name(name){}
string GetName(){
return _name;
}
};
class Website {
public:
virtual void Use(User* user) = 0;
};
class ConcreteWebsite:public Website {
private:
string _name;
public:
ConcreteWebsite(string name):_name(name){}
void Use(User* user){
cout << " 网站分类:" << _name << " 用户: " << user->GetName() << endl;
}
};
class WebsiteFactory {
private:
map<string, Website*> _flyweights;
public:
Website* GetWebsiteCategory(string key){
if(_flyweights.find(key) == _flyweights.end()){
_flyweights[key] = new ConcreteWebsite(key);
}
return _flyweights[key];
}
int GetWebsiteCount(){
return _flyweights.size();
}
};
int main(){
WebsiteFactory*f = new WebsiteFactory();
Website* fx = f->GetWebsiteCategory("项目经历");
fx->Use(new User("ToBuildAnArmy"));
Website* fy = f->GetWebsiteCategory("项目经历");
fy->Use(new User("玉竹笑"));
Website* fz = f->GetWebsiteCategory("产品展示");
fz->Use(new User("AcE&ArMs"));
Website* f1 = f->GetWebsiteCategory("404 error");
f1->Use(new User("404 error"));
cout << "网站分类总数为:" << f->GetWebsiteCount() << endl;
return 0;
}
27.解释器模式 interpreter
- 给定一个语言, 定义其文法的一种表示, 定义一个解释器, 使用该表示来解释语言中的句子
- 当一个语言需要解释执行, 该语言的句子可表示为一个抽象语法树
- 特点: 容易改变和扩展文法,
- 缺点: 为文法的每一条规则至少定义一个类, 包含多规则的文法可能难以管理维护
#include<iostream>
#include<string>
using namespace std;
class PlayContext {
private:
string _text;
public:
string GetText(){
return _text;
}
void SetText(string text){
_text = text;
}
};
class Expression {
public:
virtual void Interpret(PlayContext* context) = 0;
virtual void Excute(string key, double value) = 0;
};
class Note:public Expression {
public:
void Interpret(PlayContext* context){
string playKey = context->GetText().substr(0, 1);
// context->SetText(context->GetText().substr(2));
string text = context->GetText();
if (text.length() > 2) {
context->SetText(context->GetText().substr(2));
} else {
// Handle error
return;
}
double playValue = stod(context->GetText().substr(0, context->GetText().find(" ")));
context->SetText(context->GetText().substr(context->GetText().find(" ") + 1));
Excute(playKey, playValue);
}
void Excute(string key, double value){
string note;
if(key == "C"){
note = "1";
} else if(key == "D"){
note = "2";
} else if(key == "E"){
note = "3";
} else if(key == "F"){
note = "4";
} else if(key == "G"){
note = "5";
} else if(key == "A"){
note = "6";
} else if(key == "B"){
note = "7";
}
cout << note << " ";
}
};
class Scale:public Expression {
public:
void Interpret(PlayContext* context){
string playKey = context->GetText().substr(0, 1);
// context->SetText(context->GetText().substr(2));
string text = context->GetText();
if (text.length() > 2) {
context->SetText(context->GetText().substr(2));
} else {
// Handle error
return;
}
double playValue = stod(context->GetText().substr(0, context->GetText().find(" ")));
context->SetText(context->GetText().substr(context->GetText().find(" ") + 1));
Excute(playKey, playValue);
}
void Excute(string key, double value){
string scale;
switch((int)value){
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
}
}
};
int main() {
PlayContext* context = new PlayContext();
cout << "上海滩:";
context->SetText("O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 3");
Expression* expression = NULL;
while(context->GetText().length() > 0){
string str = context->GetText().substr(0, 1);
if(str == "O"){
expression = new Scale();
} else {
expression = new Note();
}
expression->Interpret(context);
}
return 0;
}
28.访问者模式 Visitor
- 表示一个作用于某对象结构中的各元素的操作, 可在不改变各元素的类的前提下定义作用于这些元素的新操作
- 作用: 目的要把处理从数据结构分离, 使算法操作的增加变得容易
#include<iostream>
#include<string>
using namespace std;
class Man;
class Woman;
class Action {
public:
virtual void GetManConclusion() = 0;
virtual void GetWomanConclusion() = 0;
};
class Person {
public:
virtual void Accept(Action* visitor) = 0;
};
class Success:public Action {
public:
void GetManConclusion(){
cout << "男人成功时,背后多半有一个伟大的女人。" << endl;
}
void GetWomanConclusion(){
cout << "女人成功时,背后多半有一个不成功的男人。" << endl;
}
};
class Failing:public Action {
public:
void GetManConclusion(){
cout << "男人失败时,闷头喝酒,谁也不用劝。" << endl;
}
void GetWomanConclusion(){
cout << "女人失败时,眼泪汪汪,谁也劝不了。" << endl;
}
};
class Man:public Person {
public:
void Accept(Action* visitor){
visitor->GetManConclusion();
}
};
class Woman:public Person {
public:
void Accept(Action* visitor){
visitor->GetWomanConclusion();
}
};
class ObjectStructure {
private:
Person* _elements[100];
int _size;
public:
void Attach(Person* element){
_elements[_size++] = element;
}
void Detach(Person* element){
// ...
}
void Display(Action* visitor){
for(int i = 0; i < _size; i++){
_elements[i]->Accept(visitor);
}
}
};
int main(){
ObjectStructure *o = new ObjectStructure();
o->Attach(new Man());
o->Attach(new Woman());
Success* v1 = new Success();
o->Display(v1);
Failing* v2 = new Failing();
o->Display(v2);
}