1.模式定义:
代理模式(Proxy ):定义为其他对象提供一种代理以控制对这个对象的访问。
2.模式结构
- Proxy:代理类
- Subject:抽象主题角色
- RealSubject:具体主题角色(被代理人)
3.代码分析
- 3.1 main.cpp
#include"real_subject.hpp"
#include"proxy.hpp"
int main() {
RealSubject* rs = new RealSubject();
Proxy proxy(rs);
proxy.request();
}
- 3.2 代理: proxy.hpp
#ifndef PROXY_HPP
# define PROXY_HPP
#include<iostream>
#include"./subject.hpp"
using namespace std;
// 代理类/委托类
class Proxy: public Subject {
private:
Subject* m_subject;
public:
Proxy(Subject* subject){
m_subject = subject;
}
virtual ~Proxy(){
delete m_subject;
}
void request() {
pre_request();
m_subject->request();
after_request();
}
void pre_request() {
cout << "Proxy::pre_request" << endl;
}
void after_request() {
cout << "Proxy::after_request" << endl;
}
};
#endif
- 3.3 抽象主题角色(被代理人): subject.hpp
#ifndef SUBJECT_HPP
#define SUBJECT_HPP
class Subject
{
public:
virtual void request(){};
};
#endif // SUBJECT_HPP
- 3.4 具体主题角色(代理人): real_subject.hpp
#ifndef REAL_SUBJECT_HPP
#define REAL_SUBJECT_HPP
#include<iostream>
#include"./subject.hpp"
using namespace std;
class RealSubject: public Subject
{
public:
RealSubject(){}
virtual ~RealSubject(){}
void request(){
cout << "RealSubject::request" << endl;
}
};
#endif // REAL_SUBJECT_HPP
- 3.5 实验结果:
Proxy::pre_request
RealSubject::request
Proxy::after_request
4.优缺点
-
4.1 优点
- 4.1.1 职责清晰
- 4.1.2 高扩展性
- 4.1.3 智能化(动态代理:是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。核心是一种面向横切面编程,也就是AOP(Aspect Oriented Programming))
-
4.2 缺点
- 4.2.1 由于在客户端和真实主题之间增加了代理对象,因此 有些类型的代理模式可能会造成请求的处理速度变慢。
- 4.2.2 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
5.模式分析
- 5.1 代理模式的优点在于能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 5.2 代理模式的代理类引用了真实的代理类,这样可以使一些大的对象免予深拷贝,减少内存占用。
- 5.3 虚拟(Virtual)代理[延迟代理]:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
- 5.4 代理模式的缺点在于由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
- 5.5 代理模式易于扩展,因为有代理接口存在,符合开闭原则。代理类和被代理类职责清晰符合单一职责原则。
6.实例:游戏代练(go代码实现)
-
类图:
-
6.0: main.go
package main
import (
"fmt"
"./proxy_game"
)
func test_proxy_game() {
p := proxy_game.NewGamePlayer("zs")
pp := proxy_game.NewGamePlayerProxy(p)
pxyp := proxy_game.NewProxy(pp)
pxyp.Agent()
}
func main() {
test_proxy_game()
}
- 6.1:代理接口:iproxy.go
package proxy_game
// 代理接口
type IProxyGame interface {
KillMonster() // 打怪
UpdateGrade() // 升级
}
- 6.2: 代练玩家类:playr_proxy.go
package proxy_game
import "fmt"
// 代练玩家
type GamePlayerProxy struct {
Player *GamePlayer // 被代理玩家
}
func NewGamePlayerProxy(player *GamePlayer) *GamePlayerProxy {
return &GamePlayerProxy{
Player: player,
}
}
func (p *GamePlayerProxy) KillMonster() {
p.Player.KillMonster()
fmt.Println(p.Player.name, "===>GamePlayerProxy::KillMonster")
}
func (p *GamePlayerProxy) UpdateGrade() {
p.Player.UpdateGrade()
fmt.Println(p.Player.name, "===>GamePlayerProxy::UpdateGrade")
}
- 6.3: 玩家类:player.go
package proxy_game
import "fmt"
// 正常玩家
type GamePlayer struct {
name string
}
func NewGamePlayer(name string) *GamePlayer {
return &GamePlayer{
name: name,
}
}
func (p *GamePlayer) KillMonster() {
fmt.Println(p.name, "===>GamePlayer::KillMonster")
}
func (p *GamePlayer) UpdateGrade() {
fmt.Println(p.name, "===>GamePlayer::UpdateGrade")
}
- 6.4: 代练类[代理类]:proxy.go
package proxy_game
import "fmt"
// 代理类
type Proxy struct {
proxyPlayer IProxyGame // 被代理的玩家
}
func NewProxy(proxyPlayer IProxyGame) *Proxy {
return &Proxy{
proxyPlayer: proxyPlayer,
}
}
// 代练
func (p *Proxy) Agent() {
fmt.Println("==========================================")
p.proxyPlayer.KillMonster()
fmt.Println("==========================================")
p.proxyPlayer.UpdateGrade()
fmt.Println("==========================================")
}
- 6.5 执行结果:
==========================================
代理 zs 去===>GamePlayerProxy::KillMonster
zs 去===>GamePlayer::KillMonster
==========================================
代理 zs ===>GamePlayerProxy::UpdateGrade
zs 去===>GamePlayer::UpdateGrade
==========================================