xml图阅读

+pub -pri #pro
棒棒糖表示法:圆圈旁为接口名称

  • 空心三角形+实线:继承
  • 空心三角形+虚线:接口
  • 实线箭头:关联
  • 空心菱形+实线箭头:聚合
  • 实心菱形+实线箭头:合成
  • 虚线箭头:依赖

关联、聚合、组合与依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class A;

class A_associate{
private:
A a;//关联
};

class A_group{
private:
vector<shared_ptr<A>> A_group;
void AddA(shared_ptr<A> a){
A_group.push_back(a);//聚合

}
};

class A_combine{
A_combine(A a) : m_a(make_unique<a>()){}//组合
private:
unique_ptr<A> m_a
};

class A_dependency{
void do_A_dependency(const& A_group,const& A_combine);//依赖
};

策略模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class strategy{
public:
virtual void AlgorithomInterface() = 0;
virtual ~strategy() = default;
};
class strategy_Apublic strategy{
public:
void ALlgorithomInterface(){
//实现
}
};
class strategy_Bpublic strategy{
public:
void AlgorithomInterface(){
//实现
}
};
class Contex(){
public:
Contex(unique_ptr<strategy> s) : m_strategy(move(s)){}
void ContextInterface(){
m_strategy->AlgorithomInterface();
}
private:
unique_ptr<strategy> m_strategy;
};
int main(){
Contex contex(make_unique<strategy_A>());
contex.ContexInterface();
}

单一职责

就一个类而言,应该只有一个引起它变化的原因。

开放-封闭原则

软件实体(类、模块、函数等)应该可以扩展但是不可以被修改。应对需求的变化,重构、构造抽象来隔离,对程序的改动是增加新代码,而尽量不要修改现有代码。

在最初编写代码的时候,假设变化不会发生,而当变化发生时立即创建抽象并隔离以后的同类变化。

依赖倒转

  • 高层模块不依赖低层模块,两个都应该依赖抽象。
  • 抽象不应该依赖于细节,细节应该依赖于抽象。
  • 子类必须能够替换他们的父类。
    传统的编程中,高层模块应该依赖于底层模块。而在依赖倒转原则的指导下变成了高层模块->抽象接口<-低层模块。也即是说,一个模块在需要另一个模块的时候,不应该依赖于具体的实现类,而是因该依赖于一个抽象的接口类或者父类。

因此在这条原则的指导下,模块之间应该复用的是父类或者接口,子类继承父类的全部功能,并实现特殊功能。

装饰模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

class Person{
public:
Person(string name):m_name(name){}
virtual void show(){
cout<<"装扮"<<this->m_name;
}
virtual ~Person() = default;
private:
string m_name;
};
class Finery : public Person{
public:
Finery(unique_ptr<Person> person) : m_person(person);
void show(){
if(m_person != NULL){
component->show()
}
}
protected:
unique_ptr<Person> m_person;
}
class TShirts : public Finery{
public:
using Finery::Finery();
void show(){
m_person->show();
cout<<"T恤衫 ";

}
}
class Trousers : public Finery{
public:
using Finery::Finery();
void show(){
m_person->show();
cout<<"裤子 ";
}
}
int main(){
auto person = make_unique<Person>("chen");
person = unique_ptr<Tshirts>(move(person));
person = unique_ptr<Trousers>(move(person));
person->show();
}

代理模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Interface{
virtual ~IGiveGift() = default;
virtual void GiveFlower() const = 0;
}
class SchoolGirl{
public:
SchoolGirl(string name) : m_name(name){}
string get_name(){return m_name;}
private:
string m_name;
}
class Pursuit : public Interface{
public:
Proxy(const SchoolGirl& girl) {
m_pursuit = std::make_unique<Pursuit>(std::move(girl));
}
void GiveFlower(){
//实现
}
private:
SchoolGirl m_schoolgirl;
}

class Proxy : public Interface{
public:
Proxy(const SchoolGirl& mm) : m_pursuit(mm){}
void GiveFlower(){
m_pursuit->GiveFlower();
}
private:
unique_ptr<Pursuit> m_pursuit;
}
int main(){
SchoolGirl mm("w");
Proxy proxy(mm);
proxy.GiveFlower();
}
  • 可以实现懒加载,例如通过在代理中设置使用时再初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class VirtualImageProxy : public IImage {
private:
std::string filename;
// 使用 mutable,因为我们要在 const 方法中修改它(懒加载)
mutable std::unique_ptr<RealImage> realImage;
public:
VirtualImageProxy(std::string name) : filename(std::move(name)), realImage(nullptr) {
std::cout << "[Virtual Proxy] Proxy created for " << filename << ". Real object is not created yet." << std::endl;
}

void display() const override {
std::cout << "[Virtual Proxy] Display method called." << std::endl;
// 只有在第一次调用时,realImage 为空,才创建真实对象
if (!realImage) {
std::cout << "[Virtual Proxy] Real object needed. Creating it now..." << std::endl;
realImage = std::make_unique<RealImage>(filename);
}
realImage->display();
}
};
  • 安全代理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct User { std::string username; std::string role; };

class IDocument {
public:
virtual ~IDocument() = default;
virtual void read() const = 0;
virtual void write(const std::string& content) = 0;
};

class RealDocument : public IDocument {
private:
std::string content;
public:
RealDocument() { content = "This is the original document."; }
void read() const override { std::cout << " Reading document: " << content << std::endl; }
void write(const std::string& new_content) override {
content = new_content;
std::cout << " Document successfully updated." << std::endl;
}
};

class SecurityDocumentProxy : public IDocument {
private:
std::unique_ptr<RealDocument> realDocument;
User currentUser;
public:
SecurityDocumentProxy(User user)
: realDocument(std::make_unique<RealDocument>()), currentUser(std::move(user)) {}

void read() const override {
std::cout << "[Security Proxy] " << currentUser.username << " is trying to read." << std::endl;
realDocument->read(); // 假设所有人都可以读
}

void write(const std::string& content) override {
std::cout << "[Security Proxy] " << currentUser.username << " is trying to write." << std::endl;
if (currentUser.role == "Admin") {
std::cout << " Access Granted." << std::endl;
realDocument->write(content);
} else {
std::cout << " Access Denied. User must be an Admin to write." << std::endl;
}
}
};

工厂方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//设定已经实现了加法类减法类

class Ifactory{
public:
virtual ~IFactory() = default;
virtual unique_ptr<Operation> CreatOperation() = 0;
};
class AddFactory : public IFactory{
public:
virtual unique_ptr<Operation> CreatOperation(){
return make_uniqe<OperationAdd>();
}
}
class SubFactory : public IFactory{
public:
virtual unique_ptr<Operation> CreatOperation(){
return make_uniqe<OperationSub>();
}
};
int main(){
AddFactory addFactory;
unique_ptr<Operation> oper = addFactory.CreatOperation();
int ans = oper->do_add(lhs,rhs);
}

简单工厂方法需要客户端将要执行的操作传入工厂,由工厂执行switch逻辑实例化具体类。但是这样会导致添加类时,需要修改工厂类,这对于开放-封闭原则是不可取的。

工厂方法是定义一个创建对象的接口,由子类决定实例化哪一个类。工厂方法将一个类的实例化延迟到子类。

迪米特法则

这个法则强调了类之间的松耦合,如果两个类不必彼此之间直接通信,那么这两个类就不应该产生直接的相互作用,如果一个类需要调用另一个类的某一个方法,那么可以通过第三者转发这个调用。

上面所提到的设计模式,除了原型模式(C++中深拷贝的实现),模板方式(高度抽象实现,或者直接定义模板类)。都是通过在类与类之间定义一个抽象层,实现各种操作。

外观模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class System1{
public:
void method1() {}
}
class System2{
public:
void method2() {}
}
class System3{
public:
void method3() {}
}
class System4{
public:
void method4() {}
}
class Combine{
public:
combine() = default;
Combine(System1 const& system1,System2 const& system2,System3 const& system3,System4 const& system4) : system_1(system1),system_2(system2),system_3(system3),system_4(system4){}
void scheme1(){
system_1.method1();
system_2.method2();
}
void scheme2(){
system_2.method2();
system_4.method4();
}
private:
System1 system_1;
System2 system_2;
System3 system_3;
System4 system_4;
}
int main(){
Combine combine1;
combine1.scheme2();
}

建造者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Builder{
public:
virtual ~Builder() = default;
virtual void do_build() = 0;
}
class ConcreteBuilder1 : public Builder{
public:
void do_build() {//建造产品
}
}
class ConcreteBuilder2 : public Builder{
public:
void do_build() {//建造产品

}
}
class Director{
public:
Director(unique_ptr<Builder> concrete_builder) : m_builder(concrete_builder){}
void do_director(){
m_builder->do_build();
}
private:
unique_ptr<Builder> m_builder;
}
int main(){
make_unique<ConcreteBuilder1>(b1);
Director director(b1);
director.do_director();
}

建造者模式中,创建复杂对象的算法应该独立于该对象的组成部分,以及复杂的装配方式.

观察者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class Observe{
public:
Observe(string name) : m_name(name){}
virtual ~Observe() = default;
virtual void update() = 0;
private:
string m_name;
};
class StockObserve : public Observe{
public:
using Obsere::Observe();
void update(){
cout<<"股票观察者收到";
}
};
class GameObserve : public Observe{
public:
using Obsere::Observe();
void update(){
cout<<"游戏观察者收到";
}
};
class Notification{
public:
virtual ~Notification() = default;
virtual void attach(Observe* observe) = 0;
virtual void note() = 0;
virtual void action(bool value) = 0;

};
class Secretary : public Notification{
public:
void note(){
for(const auto& abs:observe_list){
abs->update();
}
}
void attach(Observe* observe){
observe_list.push_back(observe);
}
void action(bool value){
this->status = value;
if(status){
note();
}
}
private:
vector<Observe* > observe_list;
bool status;
};
class Boss : public Notification{
public:
void note(){
for(const auto& abs:observe_list){
abs->update();
}
}
void attach(Observe* observe){
observe_list.push_back(observe);
}
void action(bool value){
this->status = value;
if(status){
cout<<"good job";
}
}
private:
vector<Observe* > observe_list;
bool status;
};

int main(){
Boss boss;
Secretary secretary;
StockObseve worker1("chen");
GameObserve worker2("li");
secretary.attach(&worker1);
secretary.attach(worker2);
secreatry.action(1);
boss.attach(&worker1);
boss.attach(worker2);
boss.action(1);
}

在实现上,既要完成观察者和主题的解耦(设置抽象层)。同时,有两种实现方式,其一(双向),是观察者订阅主题同时主题维护观察者列表,其二(单向),是仅仅主题维护观察者列表。上面实现的是单向的。

单向使用:

  • 简单的通知机制:不需要传递复杂的状态。比如,一个按钮(Subject)被点击后,通知多个监听器(Observers)执行各自的动作。
  • 日志系统:日志系统(Subject)产生日志后,通知文件记录器、数据库记录器、网络上报器(Observers)。日志信息通过update(logMessage)直接“推”过去。
  • UI更新:一个数据模型(Subject)改变后,通知多个UI组件(Observers)更新。更新所需的数据可以一次性全部通过update参数推送到UI组件。
  • 对复用性要求极高:你希望你的观察者组件可以被用在完全不同的系统中,只要对方能调用它的update方法即可。
    双向使用:
  • 观察者需要的数据非常复杂:主题的状态非常多,如果都通过update参数传递会使得方法签名异常臃肿,而且可能很多数据观察者并不关心,造成浪费。此时,让观察者按需“拉取”数据是更好的选择。
  • 不同观察者关心的数据不同:假设一个天气站(Subject)有温度、湿度、气压等多个数据。
  • 需要观察者自我管理:当观察者需要在特定条件下自动取消订阅时,双向依赖就变得很方便。比如一个临时的弹窗(Observer),当用户点击关闭后,它可以自己从通知中心(Subject)注销。

这个例子中并没有引入智能指针,原因就在于在双向的情况下使用share_ptr(unique_ptr肯定不符合,原因是要求多个观察者订阅同一个主题)会造成循环引用,导致内存泄漏。应该引入weak_ptr维护数组。另外观察者和主题的抽象层都即可以使用抽象类实现,也可以使用接口,具体要看层内的关系是什么。

最后,为了解决观察者的通知接口不一致的问题(例如观察者A、B的接口并不全是update),这个时候维护的就不是观察者列表了,而是一个handler列表,同时引入lamda函数。不得不说,这点C++相比于java这种现代语言就要麻烦很多。。。Function是一个函数指针类,它可以存储、复制和调用任何“可调用对象”,包括:

  • 普通函数指针
  • 类的成员函数指针(需要绑定一个对象实例)
  • 函数对象(Functor,即重载了 operator() 的类)
  • Lambda 表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//    返回值为 void,接收一个 const std::string& 类型的参数
using EventHandler = std::function<void(const std::string&)>;
class Notifier {
public:
void subscribe(const EventHandler& handler) {
handlers.push_back(handler);
}

void notify(const std::string& eventInfo) {
for (const auto& handler : handlers) {
handler(eventInfo); // 直接调用
}
}

private:
std::vector<EventHandler> handlers;
};
class StockWorker {
public:
StockWorker(std::string name) : m_name(name) {}
void closeStockMarket(const std::string& msg) {
std::cout << "股票同事 " << m_name << " 收到消息 '" << msg << "', 立刻关闭了股票软件!" << std::endl;
}
private:
std::string m_name;
};

class GameWorker {
public:
GameWorker(std::string name) : m_name(name) {}
void stopPlayingGame(const std::string& msg) {
std::cout << "游戏同事 " << m_name << " 收到消息 '" << msg << "', 立刻切出了游戏!" << std::endl;
}
private:
std::string m_name;
};
void logToFile(const std::string& msg) {
std::cout << "[日志记录]: 事件发生 - " << msg << std::endl;
}

int main() {
Notifier notifier;

StockWorker chen("小陈");
GameWorker li("小李");

// 1. 订阅 StockWorker 的成员函数
// 使用 Lambda 表达式捕获 chen 对象,并定义一个符合签名的函数体
notifier.subscribe([&chen](const std::string& msg) {
chen.closeStockMarket(msg);
});

// 2. 订阅 GameWorker 的成员函数
notifier.subscribe([&li](const std::string& msg) {
li.stopPlayingGame(msg);
});

// 3. 订阅一个普通的全局函数
notifier.subscribe(logToFile);

// 发出通知
notifier.notify("老板来了,快干活!");

return 0;
}

抽象工厂

在这个模式中提供了一个创建一系列相关或者相互依赖对象的接口,而且无需指定他们具体的类。

这个模式实际上就是在探讨类的划分,通过高效的划分方式,使类回归到实际的产品中,客户端通过切换工厂实现切换产品。

但切换过程中涉及到的反射技术很关键。但C++中似乎并没有类似的实现。。

状态模式

状态模式解决了当一个对象的状态转换条件表达式过于复杂的情况,它将判断逻辑转移到表示不同状态的一系列类中。其含义是当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。实现方法是内部维护了一个状态指针,通过转换指针多态,切换实现效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class State{
virtual ~State() = default;
virtual void WritePrograme() = 0;
}
class MorningState : public State{
public:
MorningState(work w):m_work(w){}
void WriteState(){
if(w.Hour<12){
cout<<" ";
}else{
w.SetState(new NoonState(w));
}
}
private:
work m_work;
}
class NoonState : public State{
public:
NoonState(work w):m_work(w){}
void WriteState(){
if(w.Hour>13){
cout<<" ";
}else{
w.SetState(new AfternoonState(w));
}
}
private:
work m_work;
}
class work{
public:
work(int hour):Hour(hour){}
void SetState(unique_ptr<State> state){
m_state = move(state);
}
void WritePrograme(){
m_state->WriteState();
}
private:
int Hour;
unique_ptr<State> m_state;
}
int main(){
work w(10);
w.WritePrograme();
w.WritePrograme();
w.WritePrograme();
w.WritePrograme();
return 0;
}

适配器模式

就是添加一层,不是有句话吗,计算机问题大都可以通过添加一层解决,要是还不行就加两层。其中包括类适配器和对象适配器,顾名思义就是对类做适配或者对实例化之后的对象做适配。不直接对类做适配的原因是java等语言不支持多重继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 目标接口 (Target): 我们的播放器只认识这个接口
class IMusicPlayer {
public:
virtual ~IMusicPlayer() = default;
virtual void play_mp3(const std::string& filename) const = 0;
};

// 被适配者 (Adaptee): 一个已存在的、接口不兼容的类
class AdvancedPlayer {
public:
void play_wav(const std::string& filename) const {
std::cout << "Advanced Player is playing WAV file: " << filename << std::endl;
}
};
//类适配器
class ClassAdapter : public IMusicPlayer, private AdvancedPlayer {
public:
void play_mp3(const std::string& filename) const override {
std::cout << "Class Adapter: Converting MP3 request to WAV." << std::endl;
// 调用从 AdvancedPlayer 继承来的方法
play_wav(filename + ".wav");
}
};
// --- 对象适配器实现 ---
class ObjectAdapter : public IMusicPlayer {
public:
// 通过构造函数传入被适配的对象
ObjectAdapter(std::shared_ptr<AdvancedPlayer> player) : adaptee(player) {}

void play_mp3(const std::string& filename) const override {
std::cout << "Object Adapter: Delegating MP3 request to WAV player." << std::endl;
// 将请求委托给持有的 adaptee 对象
adaptee->play_wav(filename + ".wav");
}

private:
std::shared_ptr<AdvancedPlayer> adaptee; // 持有被适配者的实例
};

组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Company{
Company(string name) : m_name(name){}
virtual ~Company() = default;
virtual void Add(Company* c){}
virtual void Remove(Company* c){}
virtual void Display(int depth){}
virtual void LineOfDuty(){}
private:
string m_name;
}
class ConcreteCompany : public Company{
public:
using Company::Company;
void Add(Company* c){
m_companies.push_back(c);
}
void Remove(Company* c){
m_companies.erase(remove(m_companies.begin(), m_companies.end(), c), m_companies.end());
}
void Display(int depth){
cout << string(depth, '-') << m_name << endl;
}
void LineOfDuty(){
cout << m_name << "[公司]员工管理" << endl;
}
private:
vector<Company> m_companies;
}
class HRDepartment : public Company{
public:
using Company::Company;
void Add(Company* c){}
void Remove(Company* c){}
void Display(int depth){
cout << string(depth, '-') << m_name << endl;
}
void LineOfDuty(){
cout << m_name << "[部门]员工招聘培训管理" << endl;
}
}
int main(){
Company* root = new ConcreteCompany("北京总公司");
root->Add(new HRDepartment("总公司人力资源部"));

ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
comp->Add(new HRDepartment("华东分公司人力资源部"));
root->Add(comp);
root->Display(1);
root->LineOfDuty();
return 0;
}

单例模式

经典单例模式,用的应该是最广泛的吧?下面记录几种写法

  • 懒汉式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class FormToolBox {
public:
static FormToolBox& GetInstance() {
// 这行代码在多线程环境下是安全的,且只执行一次
static FormToolBox instance;
return instance;
}
FormToolBox(const FormToolBox&) = delete;
FormToolBox& operator=(const FormToolBox&) = delete;
private:
FormToolBox() {
std::cout << "FormToolBox instance created." << std::endl;
}
~FormToolBox() = default;
};
  • 饿汉式
1
2
3
4
5
6
7
8
9
10
11
class FormToolBox {
public:
static FormToolBox& GetInstance() {
return instance;
}
FormToolBox(const FormToolBox&) = delete;
FormToolBox& operator=(const FormToolBox&) = delete;
private:
FormToolBox() = default;
static FormToolBox instance; // 在类中声明
};

在C++代码中既不需要判断instance == null,也不需要使用lock语句防止多线程同时访问。原因是初始化单例的时候,初始化的是对象而不是指针,并且是static的,不存在为空的情况。至于是否是第一次创建,编译器会检查的。另外,在C++11中,对于函数局部的静态变量,如果多个线程同时尝试初始化,那么只有一个线程会执行,其他的必须等待初始化完成,因此也就保证了static初始化是原子性和线程安全的。而在C#或者java内实现,则需要注意以上两点。

命令模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Commond{
public:
Commond(Barbecuer* reciever) : m_reciever(reciever){}
virtual void do_commond() = 0;
virtual ~Commond() = default;
protected:
Barbecuer* m_reciever;
};
class Bake_Mutton_Commond : public Commond{
public:
using Commond::Commond;
void do_commond(){
m_reciever->Bake_Mutton();
}
};
class Bake_Chicken_Commond : public Commond{
public:
using Commond::Commond;
void do_commond(){
m_reciever->Bake_Chicken();
}
};
class Waiter{
public:
void set_Orders(unique_ptr<Commond> order){
m_orders.push_back(move(order));
//记录日志
}
void CancleOrder(unique_ptr<Commond> order){
m_orders.erase(remove(m_orders.begin(), m_orders.end(), order), m_orders.end());
}
void notify(){
for(const auto& abs : m_orders){
abs->do_commond();
}
m_orders.clear();
}
private:
vector<unique_ptr<Commond>> m_orders;
};
class Barbecuer{
public:
void Bake_Mutton(){
cout<<"烤羊肉";
}
void Bake_Chicken(){
cout<<"烤鸡肉";
}
};
int main(){
Barbecuer reciever;
Barbecuer* reciever_ptr = & reciever;
Waiter waiter;
waiter.set_Orders(make_unique<Bake_Mutton_Commond>(reciever_ptr));
waiter.set_Orders(make_unique<Bake_Chicken_Commond>(reciever_ptr));
waiter.notify();
}

职责链模式

这个模式的关键在于发出请求的客户端并不知道链条当中哪一个对象最终处理这个请求。这样系统的更改可在不影响客户端的情况下动态重新组织和分配责任。其含义是,使多个对象都有机会处理请求,要避免请求发送者和接收者之间的耦合关系。将对象连成一条链并沿着这条链传递请求,直到一个对象处理它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class manager{
public:
void do_request(int i){
if(i>0&&i<10){
cout<<"manage success"
}else{
superior.do_request();
}
}
private:
boss superior;
}
class boss{

}

访问者模式

我认为这个模式的精髓在于双分配的实现,通过第一次分配确认类别,返回this指针。根据this指针做第二次分配实现具体功能。其含义是表述作用于某个对象结构中的各个元素的操作。可以实现不改变各个元素的类的前提下定义作用于这些元素的新操作。到那时就像书中所说,必须保证第一次分配的类别是固定的,否则重构的麻烦程度会大大增加。(即数据结构和算法分开)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Function_Visitor{
public:
virtual void FucntionVisitor_of_A(DBElementA* A) = 0;
virtual void FucntionVisitor_of_B(DBElementB* B) = 0;
virtual ~Function_Visitor() = default;
}
class ConsreteFunctionVisitor1 : public Function_Visitor{
public:
void FucntionVisitor_of_A(DBElementA* A){ //实现
}
void FucntionVisitor_of_B(DBElementB* B){ //实现
}
}
class ConsreteFunctionVisitor2 : public Function_Visitor{
public:
void FucntionVisitor_of_A(DBElementA* A){ //实现
}
void FucntionVisitor_of_B(DBElementB* B){ //实现
}
}
class DBElement{
public:
virtual void Accept(Function_Visitor& v) = 0;
virtual ~DBElement() = default;
}
class DBElementA : public DBElement{
void Accept(Function_Visitor& a){
a.FucntionVisitor_of_A(this)
}
}
class DBElementB : public DBElement{
void Accept(Function_Visitor& b){
b.FucntionVisitor_of_B(this)
}
}
class ObjectStructure{
void attach(share_ptr<DBElement> element){
Element_list.push_back(move(element))
}
void accept(Function_Visitor& ConcreteVisitor){
for(auto i : Element_list){
i->Accept(ConcreteVisitor)
}
}
private:
vector<share_ptr<DBElement>> Element_list;
}

int main() {
ObjectStructure structure;
structure.attach(std::make_shared<DBElementA>());
structure.attach(std::make_shared<DBElementB>());

ConcreteFunctionVisitor1 visitor1;
std::cout << "--- Applying Visitor 1 ---" << std::endl;
structure.accept(visitor1);

ConcreteFunctionVisitor2 visitor2;
std::cout << "\n--- Applying Visitor 2 ---" << std::endl;
structure.accept(visitor2);

return 0;
}

本站由 Edison.Chen 创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

undefined