Compare commits
2 Commits
c5a592d78b
...
996187203f
| Author | SHA1 | Date | |
|---|---|---|---|
| 996187203f | |||
| f00a7d284e |
63
13_proxy.cpp
Normal file
63
13_proxy.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
class Service {
|
||||||
|
public:
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int write() = 0;
|
||||||
|
virtual ~Service() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RawService : public Service {
|
||||||
|
public:
|
||||||
|
virtual int read() override {
|
||||||
|
cout << "read succeed" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int write() override {
|
||||||
|
cout << "write succeed" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inherit from the same interface to so that the proxy class
|
||||||
|
// and the target class can be used in the same way.
|
||||||
|
class UserServiceProxy : public Service {
|
||||||
|
// Use pointers instead of inheritance to reduce coupling.
|
||||||
|
shared_ptr<RawService> rs;
|
||||||
|
const string role;
|
||||||
|
public:
|
||||||
|
UserServiceProxy(const string& s) : role(s) {
|
||||||
|
rs = make_shared<RawService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int read() override {
|
||||||
|
return rs->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int write() override {
|
||||||
|
// Implement peripheral logic here, separating it from the core logic.
|
||||||
|
if (role != "admin") {
|
||||||
|
cout << "write failed: permission denied" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs->write();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
UserServiceProxy admin("admin");
|
||||||
|
admin.read();
|
||||||
|
admin.write();
|
||||||
|
|
||||||
|
UserServiceProxy user("user");
|
||||||
|
user.read();
|
||||||
|
user.write();
|
||||||
|
}
|
||||||
80
14_chain_of_responsibility.cpp
Normal file
80
14_chain_of_responsibility.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Request {
|
||||||
|
public:
|
||||||
|
int days;
|
||||||
|
enum {
|
||||||
|
PERSONAL_LEAVE,
|
||||||
|
ANNUAL_LEAVE,
|
||||||
|
} reason;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Handler {
|
||||||
|
shared_ptr<Handler> next;
|
||||||
|
public:
|
||||||
|
void next_handle(const Request& r) {
|
||||||
|
if (!next) {
|
||||||
|
cout << "Request unhandled" << endl;
|
||||||
|
}
|
||||||
|
next->handle(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_next(shared_ptr<Handler> n) {
|
||||||
|
next = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void handle(const Request& r) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LeaderHandler : public Handler {
|
||||||
|
public:
|
||||||
|
virtual void handle(const Request& r) override {
|
||||||
|
if (r.days < 3) {
|
||||||
|
cout << "Leader: OK" << endl;
|
||||||
|
} else {
|
||||||
|
next_handle(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SupervisorHandler : public Handler {
|
||||||
|
public:
|
||||||
|
virtual void handle(const Request& r) override {
|
||||||
|
if (r.days < 7 || r.reason == Request::ANNUAL_LEAVE) {
|
||||||
|
cout << "Supervisor: OK" << endl;
|
||||||
|
} else {
|
||||||
|
next_handle(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ManagerHandler : public Handler {
|
||||||
|
public:
|
||||||
|
virtual void handle(const Request& r) override {
|
||||||
|
cout << "Manager: OK" << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto lh = make_shared<LeaderHandler>();
|
||||||
|
auto sh = make_shared<SupervisorHandler>();
|
||||||
|
auto mh = make_shared<ManagerHandler>();
|
||||||
|
|
||||||
|
lh->set_next(sh);
|
||||||
|
sh->set_next(mh);
|
||||||
|
|
||||||
|
Request r1 {1, Request::PERSONAL_LEAVE};
|
||||||
|
Request r2 {4, Request::ANNUAL_LEAVE};
|
||||||
|
Request r3 {10, Request::PERSONAL_LEAVE};
|
||||||
|
|
||||||
|
lh->handle(r1);
|
||||||
|
lh->handle(r2);
|
||||||
|
lh->handle(r3);
|
||||||
|
}
|
||||||
14
notes.md
14
notes.md
@ -83,3 +83,17 @@
|
|||||||
在创建同一类的大量对象实例时,往往会面临内存占用过高的问题。这种情况的一个常见原因是:对象实例中包含了大量冗余的、可以共享的数据。例如,在游戏开发中,多个实体可能共用相同的模型和贴图资源。如果每个实例都独立持有这些资源,就会造成不必要的内存浪费。
|
在创建同一类的大量对象实例时,往往会面临内存占用过高的问题。这种情况的一个常见原因是:对象实例中包含了大量冗余的、可以共享的数据。例如,在游戏开发中,多个实体可能共用相同的模型和贴图资源。如果每个实例都独立持有这些资源,就会造成不必要的内存浪费。
|
||||||
|
|
||||||
为了解决这一问题,享元模式提供了一种有效的解决方案。它的核心思想是将对象的数据划分为可共享的和不可共享的。在实现过程中,享元模式通常通过一个享元工厂来统一管理和缓存内部状态。当需要创建新对象时,工厂会首先检查是否已有对应的内部状态资源,若有则复用,从而避免重复实例化共享部分,显著降低内存开销。
|
为了解决这一问题,享元模式提供了一种有效的解决方案。它的核心思想是将对象的数据划分为可共享的和不可共享的。在实现过程中,享元模式通常通过一个享元工厂来统一管理和缓存内部状态。当需要创建新对象时,工厂会首先检查是否已有对应的内部状态资源,若有则复用,从而避免重复实例化共享部分,显著降低内存开销。
|
||||||
|
|
||||||
|
## 代理模式(Proxy)
|
||||||
|
|
||||||
|
我们在使用一个类时,有时会觉得这个类的功能较简单,实际使用需要额外添加一些访问控制,缓存管理等功能。简单的想法是直接在这个类中添加这些功能,但这会使得这个类急剧膨胀,且核心功能变得不那么明确。
|
||||||
|
|
||||||
|
代理模式解决了这个问题。通过一个代理类实现目标类相同接口,客户端使用代理时就像在直接操作目标类。代理类内部有目标类的指针,在处理缓存、权限等逻辑后再去调用目标类的相关函数,从而做到外围与核心逻辑的分离。
|
||||||
|
|
||||||
|
## 责任链模式(Chain of Responsibility)
|
||||||
|
|
||||||
|
有时我们会遇到如何处理用户请求的框架。一种做法是通过条件判断,得到不同条件下请求对应的处理函数。这样的话耦合严重,各个不同的 handler 需要放在一个函数或类中,每次扩展都需要改变这个类。
|
||||||
|
|
||||||
|
责任链模式解决了这个问题。一个 handler 要么处理这个请求,要么交给下一个 handler 处理,增加处理逻辑时,只需要新增一个 handler,并且正确设置相应的 next 即可。这样,每个 handler 只关心自己的职责,所有 handler 处理清晰。当我们能将所有的 handler 组成一个链式或者树式的结构时,这会非常有用。
|
||||||
|
|
||||||
|
但也正如前面提到的,这不自然支持“一个请求需多个处理者同时处理”的场景。此时可以通过责任链进一步推广成“责任网”,观察者模式,流程引擎式结构等,增强责任链模式的处理能力。
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user