上周温习了代理模式: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)之 强制代理(强校验,防绕过)的更多相关文章

  1. 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释

    代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...

  2. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  3. 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  4. 二十四种设计模式:代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...

  5. 代理模式(Proxy pattern)

    代理模式(proxy pattern):作用:为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端对象和目标对象之间起中介的作用. 代理模式涉及到的角色: 抽象角色:声明真实对象和代理对象 ...

  6. 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)

    设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...

  7. 设计模式——代理模式(Proxy Pattern)

    代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. UML图: 模型设计: Subject类: package com.cnblog.clarck; /** * Subject 类 ...

  8. 设计模式(十三):从“FQ”中来认识代理模式(Proxy Pattern)

    我们知道Google早就被墙了,所以FQ才能访问Google呢,这个“FQ”的过程就是一个代理的过程.“代理模式”在之前的博客中不止一次的提及过,之前的委托回调就是代理模式的具体应用.今天我们就从“F ...

  9. 13.代理模式(Proxy Pattern)

    using System; namespace Test { //抽象角色:声明真实对象和代理对象的共同接口. //代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象, //同时代理 ...

  10. 你管这叫代理模式(Proxy Pattern)

    代理模式   代理模式即给一个真实类提供一个代理类,该代理类代替真实类完成其功能,一般还可在代理类上添加一些真实类不具有的附加功能,通俗来讲代理模式就是我们生活中常见的中介,代理模式又可分为静态代理和 ...

随机推荐

  1. Weekly Contest 128

    1012. Complement of Base 10 Integer Every non-negative integer N has a binary representation.  For e ...

  2. 学习 swift (1)

    https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwi ...

  3. 设置jade高亮

    来自:https://segmentfault.com/a/1190000002896247 打开sublime3,再打开 view > show console,把下列代码复制到console ...

  4. css基础小总结

    header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...

  5. xp——极限编程的几个方法

    最近阅读<Head First Java>一书时,看到极限编程(XP)的概念,觉得很有趣,摘抄下来以备后期继续学习. 极限编程(XP)是一种新型的软件开发方法论.他的构想是结合了许多种&q ...

  6. 微信小程序组件化实践

    Do Not Repeat Yourself 如何提高代码质量,方法有许多:抽象.模块.组件化,我认为它们的中心点都是--Do Not Repeat Yourself. 小程序组件化 我们先看看小程序 ...

  7. linux对文件赋权限的命令chmod的详细说明

    指令名称 : chmod使用权限 : 所有使用者 使用方式 : chmod [-cfvR] [--help] [--version] mode file... 说明 : Linux/Unix 的档案调 ...

  8. 【bzoj2789】 Letters 树状数组

    又是一道树状数组求逆序对的题目. 这一题我们可以将第二个串中的每一个字母,与第一个串中的字母做两两匹配,令第二个串第i个字母的值id[i]为该字母与第一个串中的字母匹配到的位置. 然后考虑到所求答案为 ...

  9. 用asp.net core 2.0 + EFCore.Sqlite做个小网站

    许久没用C#写程序.听说进来发生大事,.NetCore2.0发布了,于是便学习了下,本站也应运而生. 大多数的地方按照官方的文档起步走就可以了,这里谈谈遇到的几个坑. 首先,本站是基于ASP.NetC ...

  10. 剑指offer四十之数组中只出现一次的数字

    一.题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 二.思路 建一个hashMap,统计各数字出现的次数,然后遍历hashMap,输出出现一次的数字 ...