设计模式学习——代理模式(Proxy Pattern)之 强制代理(强校验,防绕过)
上周温习了代理模式:http://www.cnblogs.com/chinxi/p/7354779.html
在此进行拓展,学习强制代理。但是发现网上大多例子都有个“天坑”(我是这么认为的),在得到代理类之后,真实对象也可以使用自己的方法,绕过了代理,这样使得代理没有了意义。
关于强制代理,字面上意思很清晰,即:
1、只能通过真实对象获取代理类来访问方法
2、其他方法比如直接new 一个代理类 访问方法(不通过本体获取),或是自己通过本体直接调用,都不行
网络上搜到的例子大多是这样的:
1、真实对象有个私有成员,this.proxy,类型为基类的指针
2、真实对象中有方法,在最开始先判断是否为代理
3、判断的方法也很简单,即判断this.proxy是否为空
4、get_proxy的方法也很简单,new出一个代理类赋值给thix.proxy,然后return
网络上搜到的大多数例子是这样的:先用真实对象直接访问方法,再用不通过真实对象得到的代理类访问方法,最后用get_proxy得到的代理类,只有最后一次成功了。乍一看似乎符合强制代理,但细细推敲后发现,至少少了一种情况,就是在通过真实对象得到代理之后,真实对象也可以访问自己的方法了。原因很简单,判断是否为代理的方法,只是判断this.proxy是否为空,而在get_proxy中,已经给this.proxy赋值,此时它非空,真实对象自然可以绕过代理,使用方法了。
用上周的例子,与网络上搜到的方式就是:
车站出了新政策,自己不卖车票,但是可以通过自己想买什么票,得知要去哪里买(代理)。

在上周的类图上做了修改,去掉了Tickets的派生类(简单点....),与Proxy中独有的方法。在此,不把get_proxy方法写进基类,由派生类决定自己是否需要代理。
代理实现,也先用判断_proxy是否为空。最后会有修改版本。
///
/// @file Selling_Tickets.h
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:35:28
/// #ifndef __SELLING_TICKETS_H__
#define __SELLING_TICKETS_H__ #include <iostream> namespace marrs{ using std::cout;
using std::endl;
using std::string; class SellingTickets
{
public:
virtual ~SellingTickets(){} public:
virtual void Selling() = ;
virtual void Price() = ; }; } #endif // __SELLING_TICKETS_H__
///
/// @file Tickets.h
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:39:17
/// #ifndef __TICKETS_H__
#define __TICKETS_H__ #include "Selling_Tickets.h" namespace marrs{
class Proxy;
class Tickets
: public SellingTickets
{
public:
Tickets(string ticket_type);
public:
void Selling();
void Price(); public:
Proxy * Get_Proxy(); private:
bool Is_Proxy(); private:
Proxy * _proxy;
string _ticket_type;
}; } #endif // __TICKETS_H__
///
/// @file Proxy.h
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:46:13
/// #ifndef __PROXY_H__
#define __PROXY_H__ #include "Selling_Tickets.h" namespace marrs{
class Tickets;
class Proxy
: public SellingTickets
{
public:
Proxy(Tickets * ticket); public:
void Selling();
void Price(); private:
Tickets * _ticket; }; } #endif // __PROXY_H__
///
/// @file Tickets.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-19 14:38:00
/// #include "Tickets.h"
#include "Proxy.h" namespace marrs{ Tickets::Tickets(string ticket_type)
: _ticket_type(ticket_type)
{ } void Tickets::Selling()
{
if(Is_Proxy())
{
cout << "sell: " << _ticket_type << endl;
}
} void Tickets::Price()
{
if(Is_Proxy())
{
cout << "price: 100 RMB" << endl;
}
} Proxy * Tickets::Get_Proxy()
{
if(!_proxy)
{
_proxy = new Proxy(this);
}
return _proxy;
} bool Tickets::Is_Proxy()
{
if(!_proxy)
{
cout << "please use proxy" << endl;
return false;
}
return true;
} }
///
/// @file Proxy.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-19 14:52:18
/// #include "Proxy.h"
#include "Tickets.h" namespace marrs{ Proxy::Proxy(Tickets * ticket)
: _ticket(ticket)
{
} void Proxy::Selling()
{
_ticket->Selling();
} void Proxy::Price()
{
_ticket->Price();
} }
现在,先用前面搜到的例子进行测试:
///
/// @file Student.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:51:42
/// #include "Proxy.h"
#include "Tickets.h" using namespace marrs; int main()
{
Tickets * ticket = new Tickets("bus_ticket");
ticket->Price();
ticket->Selling(); Proxy * proxy = new Proxy(ticket);
proxy->Price();
proxy->Selling();
delete proxy; proxy = ticket->Get_Proxy();
proxy->Price();
proxy->Selling();
delete proxy; delete ticket; return ;
}
编译,运行:
[ccx@ubuntu ~/object-oriented/Proxy_Pattern_2]$>g++ * -o main.exe
[ccx@ubuntu ~/object-oriented/Proxy_Pattern_2]$>./main.exe
please use proxy
please use proxy
please use proxy
please use proxy
price: RMB
sell: bus_ticket
看着像是强制代理了。好,现在修改一下main:
///
/// @file Student.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:51:42
/// #include "Proxy.h"
#include "Tickets.h" using namespace marrs; int main()
{
Tickets * ticket = new Tickets("bus_ticket");
Proxy * proxy = ticket->Get_Proxy();
Proxy * proxy_other = new Proxy(ticket); proxy->Price();
proxy->Selling(); ticket->Price();
ticket->Selling(); proxy_other->Price();
proxy_other->Selling(); delete proxy;
delete ticket; return ;
}
[ccx@ubuntu ~/object-oriented/Proxy_Pattern_2]$>g++ * -o main.exe
[ccx@ubuntu ~/object-oriented/Proxy_Pattern_2]$>./main.exe
price: RMB
sell: bus_ticket
price: RMB
sell: bus_ticket
price: RMB
sell: bus_ticket
结果完全符合预期,真实对象也可以使用自己的方法了。甚至乱套了,随便来个代理都可以用了。
于是,我对其进行修改,对判断是不是proxy加了点东西:
version 1:
此方法设置了唯一代理
///
/// @file Tickets.h
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:39:17
/// #ifndef __TICKETS_H__
#define __TICKETS_H__ #include "Selling_Tickets.h" namespace marrs{
class Proxy;
class Tickets
: public SellingTickets
{
public:
Tickets(string ticket_type);
~Tickets();
public:
void Selling(Proxy * proxy);
void Price(Proxy * proxy); private:
void Selling();
void Price(); public:
Proxy * Get_Proxy(); private:
bool Is_Proxy(Proxy * proxy) const; private:
string _ticket_type;
Proxy * _proxy;
}; } #endif // __TICKETS_H__
///
/// @file Proxy.h
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:46:13
/// #ifndef __PROXY_H__
#define __PROXY_H__ #include "Selling_Tickets.h" namespace marrs{
class Tickets;
class Proxy
: public SellingTickets
{
public:
Proxy(Tickets * ticket); public:
void Selling();
void Price(); private:
Tickets * _ticket; }; } #endif // __PROXY_H__
///
/// @file Tickets.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-19 14:38:00
/// #include "Tickets.h"
#include "Proxy.h" namespace marrs{ Tickets::Tickets(string ticket_type)
: _ticket_type(ticket_type)
, _proxy(NULL)
{ } Tickets::~Tickets()
{
if(_proxy)
{
delete _proxy;
}
} void Tickets::Selling(Proxy * proxy)
{
if(Is_Proxy(proxy))
{
Selling();
}
} void Tickets::Price(Proxy * proxy)
{
if(Is_Proxy(proxy))
{
Price();
}
} void Tickets::Selling()
{
cout << "sell: " << _ticket_type << endl;
} void Tickets::Price()
{
cout << "price: 100 RMB" << endl;
} Proxy * Tickets::Get_Proxy()
{
if(!_proxy)
{
_proxy = new Proxy(this);
return _proxy;
}
return NULL;
} bool Tickets::Is_Proxy(Proxy * proxy) const
{
if(proxy != _proxy)
{
cout << "please use proxy" << endl;
return false;
}
return true;
} }
///
/// @file Proxy.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-19 14:52:18
/// #include "Proxy.h"
#include "Tickets.h" namespace marrs{ Proxy::Proxy(Tickets * ticket)
: _ticket(ticket)
{
} void Proxy::Selling()
{
_ticket->Selling(this);
} void Proxy::Price()
{
_ticket->Price(this);
} }
///
/// @file Student.cc
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-08-13 20:51:42
/// #include "Proxy.h"
#include "Tickets.h" using namespace marrs; int main()
{
Tickets * ticket = new Tickets("bus_ticket");
Proxy * proxy = ticket->Get_Proxy(); proxy->Price();
proxy->Selling(); Proxy * proxy_other = new Proxy(ticket);
proxy_other->Price();
proxy_other->Selling(); ticket->Price(proxy);
ticket->Selling(proxy); ticket->Price(proxy_other);
ticket->Selling(proxy_other); delete proxy_other;
delete ticket; return ;
}
[ccx@ubuntu ~/object-oriented/Proxy_Pattern_3]$>g++ *.h *.cc -o main.exe
[ccx@ubuntu ~/object-oriented/Proxy_Pattern_3]$>./main.exe
price: RMB
sell: bus_ticket
please use proxy
please use proxy
price: RMB
sell: bus_ticket
please use proxy
please use proxy
这样的话,还有点小问题,就是真实对象可以通过传入代理的指针来访问自己的方法。但是,如果不传参的话,是用不了的。基类的那两个方法,在Ticket中,写进了private。还有,此方法目前缺少一个回收代理的方法。万一另一个地方要用的话,就用不了了。
version 2
version 2 其实就是把传参改成了随机字符串,此字符串在get_proxy中生成,并传入Proxy对象中,只有代理和真实对象知道那是什么。这里就不实现了,跟version 1 差不多的。
version 3
多个代理
此方法只不过是在真实对象Ticket中增加私有成员map<Proxy * , int> ,用来存储自己的多个代理,为version 2 的多代理版本。此处也不实现了。
version 4
使用引用计数
此方法也是version 2 的多代理版本,增加引用计数。计数归0时回收代理对象。
注:version 1 - 4都是我自己瞎想的....虽能实现,但是不知道是否实用。
设计模式学习——代理模式(Proxy Pattern)之 强制代理(强校验,防绕过)的更多相关文章
- 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释
代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...
- 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)
原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...
- 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 二十四种设计模式:代理模式(Proxy Pattern)
代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...
- 代理模式(Proxy pattern)
代理模式(proxy pattern):作用:为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端对象和目标对象之间起中介的作用. 代理模式涉及到的角色: 抽象角色:声明真实对象和代理对象 ...
- 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)
设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...
- 设计模式——代理模式(Proxy Pattern)
代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. UML图: 模型设计: Subject类: package com.cnblog.clarck; /** * Subject 类 ...
- 设计模式(十三):从“FQ”中来认识代理模式(Proxy Pattern)
我们知道Google早就被墙了,所以FQ才能访问Google呢,这个“FQ”的过程就是一个代理的过程.“代理模式”在之前的博客中不止一次的提及过,之前的委托回调就是代理模式的具体应用.今天我们就从“F ...
- 13.代理模式(Proxy Pattern)
using System; namespace Test { //抽象角色:声明真实对象和代理对象的共同接口. //代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象, //同时代理 ...
- 你管这叫代理模式(Proxy Pattern)
代理模式 代理模式即给一个真实类提供一个代理类,该代理类代替真实类完成其功能,一般还可在代理类上添加一些真实类不具有的附加功能,通俗来讲代理模式就是我们生活中常见的中介,代理模式又可分为静态代理和 ...
随机推荐
- 模糊测试之AVI文件分析
本次试验主要是针对AVI的处理,了解AVI的基本概念,并且掌握AVI文件常用的程序读写方法.知道AVI视频文件的帧的读取方法,以及了解BMP和AVI的基本关系. 本文作者:i春秋签约作家——天天 一 ...
- svn自己的一些使用方法总结
1,先创建一个空的文件夹,该文件夹是放置你们的项目代码用的.右击该文件夹,点击SVN Checkout.拿到项目负责人给你的项目目录url(例:https://192.168.0.127/svn/yo ...
- Android多媒体整体架构图
Android多媒体整体架构图 MediaPlayer框架图 Camera框架图 SoundRecorder框架图 VideoCamera框架图 OpenCore与Skia ALSA Audio框架图 ...
- class字节码结构(三)(字段集合的结构)
<Java虚拟机原理图解>1.4 class文件中的字段表集合--field字段在class文件中是怎样组织的 字段区:包括了字段计数器和字段数据区: 字段是指在类中定义的静态或者非静态的 ...
- Python小白学习之路(十七)—【内置函数二】
序列操作类函数 all() 功能:判断可迭代对象的每个元素是否都为True值注意:If the iterable is empty, return True.(举例3) 回顾:None '' ...
- OpenCV --- 修改图像的对比度、亮度 、RGB转Gray图像、修改图像的尺寸
#include <opencv2/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgu ...
- C++命名空间、函数重载、缺省参数、内联函数、引用
一 .C++入门 1.C++关键字 2.命名空间 3.C++输入&输出 4.缺省参数 5.函数重载 6.引用 7.内联函数 8.auto关键字 9.基于范围的for循环 10.指针空值null ...
- 设置pip源头地址
更新pip源 1 . 可以直接在pip时加入参数 比如: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mysqldb 2 . 修改默 ...
- Chapter 3 Phenomenon——17
Dr. Cullen raised his eyebrows. "Do you want to stay?" Cullen医生抬起了他的眉毛“你想待在这吗?” "No, ...
- vue-resource使用笔记
基本语法 //基于全局Vue对象使用http Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback); Vue ...