设计模式学习——代理模式(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)
代理模式 代理模式即给一个真实类提供一个代理类,该代理类代替真实类完成其功能,一般还可在代理类上添加一些真实类不具有的附加功能,通俗来讲代理模式就是我们生活中常见的中介,代理模式又可分为静态代理和 ...
随机推荐
- Flask从入门到精通之Jinja2模板引擎
我们使用一个简单的例子切入到Jinja2模板引擎,形式最简单的Jinja2模板引擎就是一个包含响应文本的文件,实例如下: <h1>Hello World!</h1> 最简单的包 ...
- Bind读取配置到C#实例
1.创建一个空的ASP.NET Core Web 应用程序 2.程序包管理控制台执行Install-Package Microsoft.AspNetCore -Version 2.0.1 3.创建js ...
- android应用程序的混淆打包
android应用程序的混淆打包 1 . 在工程文件project.properties中加入下proguard.config=proguard.cfg , 如下所示: target=android- ...
- PKUWC 2018 铁牌记
Day –INF: 联赛后根据分数一部分人继续停课.由于本蒟蒻撞上了狗屎运,联赛分数还行,可参加NOIWC和PKUWC,故继续停课训练.期间补全了一堆知识点,并成功翘掉期末考.(然而该还的还是要还的, ...
- C语言 for循环之阶乘的算法
int n; scanf("%d", &n); int fact = 1; int i = 1; while ( i <= n ) { fact *=i; i++; ...
- PowerDesigner最基础的使用方法入门学习(转)
PowerDesigner最基础的使用方法入门学习 1:入门级使用PowerDesigner软件创建数据库(直接上图怎么创建,其他的概念知识可自行学习) 我的PowerDesigner版本是16. ...
- openerp学习笔记 视图样式(表格行颜色、按钮,字段只读、隐藏,按钮状态、类型、图标、权限,group边距,聚合[合计、平均],样式)
表格行颜色: <tree string="请假单列表" colors="red:state == 'refuse';blue:state = ...
- Java之IO(十四)IO包中其它类
转载请注明出处:http://www.cnblogs.com/lighten/p/7267553.html 1.前言 此章介绍IO包中剩余未介绍的几个流和工具类,包括LineNumberReader. ...
- spring 接收前台ajax传来的参数的几个方法
知识补充 JSON.stringify(), 将value(Object,Array,String,Number...)序列化为JSON字符串JSON.parse(), 将JSON数据解析为js原生值 ...
- PHP CURL 伪造IP和来路
//随机IP function Rand_IP(){ $ip2id= round(rand(, ) / ); //第一种方法,直接生成 $ip3id= round(rand(, ) / ); $ip4 ...