设计模式学习——代理模式(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)
代理模式 代理模式即给一个真实类提供一个代理类,该代理类代替真实类完成其功能,一般还可在代理类上添加一些真实类不具有的附加功能,通俗来讲代理模式就是我们生活中常见的中介,代理模式又可分为静态代理和 ...
随机推荐
- 二,windows下安装memcached服务
window下安装memcached服务的流程如下: 1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached 2. 在终端(也即cmd命令界面)下输入 ‘c ...
- 从getwebshell到绕过安全狗云锁提权再到利用matasploit进服务器
本文作者:i春秋签约作家——酷帥王子 一. 利用getwebshell篇 首先对目标站进行扫描,发现是asp的,直接扫出网站后台和默认数据库,下载解密登陆如图: 下面进后台发现有fckeditor,而 ...
- 快速滑动时 `cellForRow` 的调用次数
问题 有一个 1000 个 cell 的 tableView,刚刚进入界面时,contentOffset 为 0.用手快速滑动 tableView,直至最下面一个 cell 显示在屏幕上. 这个过程中 ...
- (转)ReentrantLock可重入锁的使用场景
原文: http://my.oschina.net/noahxiao/blog/101558
- 【xsy1144】选物品 主席树
题目大意:$N$ 件物品摆成一排,给每个物品定义两个属性 $A$ 和$ B$,两件物品的 差异度 定义为它们两种属性的差的绝对值中较大的一个.如果要求出一些物品的差异度,我们先定义一个 理想物品,使它 ...
- 屏蔽百度及其广告的部分Host
127.0.0.44 www.baidu.com127.0.0.44 cpro.baidu.com127.0.0.44 hm.baidu.com127.0.0.44 bdimg.share.baidu ...
- csc命令
CSC.exe把Visual C#程序代码编译成IL文件时,有着很多参数和开关选项.正确的了解和运用这些参数和开关有时会解 决一些看似很棘手的问题.下面就通过一张表来大致说明一下这些参数和开关的具体作 ...
- Java之集合(二十五)ConcurrentHashMap
转载请注明源出处:http://www.cnblogs.com/lighten/p/7520808.html 1.前言 本章介绍使用的最频繁的并发集合类之一ConcurrentHashMap,之前介绍 ...
- EF基础知识小记四(数据库=>模型设计器)
EF基础知识小记三(设计器=>数据库)介绍了如何创建一个空设计器模型,并如何将模型同步到数据库的表中,本文则主要介绍如何将一个存在的数据库同步到模型设计器中.为了能快速的模拟这个过程,给出一下建 ...
- CentOS 配置使用 EPEL YUM 源
EPEL(Extra Packages for Enterprise Linux)是一个由特别兴趣小组创建.维护并管理的,针对 红帽企业版 Linux(RHEL)及其衍生发行版(比如 CentOS. ...