设计模式学习——代理模式(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是否为空。最后会有修改版本。

 1  ///
 2  /// @file    Selling_Tickets.h
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:35:28
 5  ///
 6
 7 #ifndef __SELLING_TICKETS_H__
 8 #define __SELLING_TICKETS_H__
 9
10 #include <iostream>
11
12 namespace marrs{
13
14 using std::cout;
15 using std::endl;
16 using std::string;
17
18 class SellingTickets
19 {
20     public:
21         virtual ~SellingTickets(){}
22
23     public:
24         virtual void Selling() = 0;
25         virtual void Price() = 0;
26
27 };
28
29 }
30
31 #endif // __SELLING_TICKETS_H__
 1  ///
 2  /// @file    Tickets.h
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:39:17
 5  ///
 6
 7 #ifndef __TICKETS_H__
 8 #define __TICKETS_H__
 9
10 #include "Selling_Tickets.h"
11
12 namespace marrs{
13 class Proxy;
14 class Tickets
15 : public SellingTickets
16 {
17     public:
18         Tickets(string ticket_type);
19     public:
20         void Selling();
21         void Price();
22
23     public:
24         Proxy * Get_Proxy();
25
26     private:
27         bool Is_Proxy();
28
29     private:
30         Proxy * _proxy;
31         string _ticket_type;
32 };
33
34 }
35
36 #endif // __TICKETS_H__
 1  ///
 2  /// @file    Proxy.h
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:46:13
 5  ///
 6
 7 #ifndef __PROXY_H__
 8 #define __PROXY_H__
 9
10 #include "Selling_Tickets.h"
11
12 namespace marrs{
13 class Tickets;
14 class Proxy
15 : public SellingTickets
16 {
17     public:
18         Proxy(Tickets * ticket);
19
20     public:
21         void Selling();
22         void Price();
23
24     private:
25         Tickets * _ticket;
26
27 };
28
29 }
30
31 #endif // __PROXY_H__
 1  ///
 2  /// @file    Tickets.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-19 14:38:00
 5  ///
 6
 7 #include "Tickets.h"
 8 #include "Proxy.h"
 9
10 namespace marrs{
11
12 Tickets::Tickets(string ticket_type)
13 : _ticket_type(ticket_type)
14 {
15
16 }
17
18 void Tickets::Selling()
19 {
20     if(Is_Proxy())
21     {
22         cout << "sell: " << _ticket_type << endl;
23     }
24 }
25
26 void Tickets::Price()
27 {
28     if(Is_Proxy())
29     {
30         cout << "price: 100 RMB" << endl;
31     }
32 }
33
34 Proxy * Tickets::Get_Proxy()
35 {
36     if(!_proxy)
37     {
38         _proxy = new Proxy(this);
39     }
40     return _proxy;
41 }
42
43 bool Tickets::Is_Proxy()
44 {
45     if(!_proxy)
46     {
47         cout << "please use proxy" << endl;
48         return false;
49     }
50     return true;
51 }
52
53 }
 1  ///
 2  /// @file    Proxy.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-19 14:52:18
 5  ///
 6
 7 #include "Proxy.h"
 8 #include "Tickets.h"
 9
10 namespace marrs{
11
12 Proxy::Proxy(Tickets * ticket)
13 : _ticket(ticket)
14 {
15 }
16
17 void Proxy::Selling()
18 {
19     _ticket->Selling();
20 }
21
22 void Proxy::Price()
23 {
24     _ticket->Price();
25 }
26
27 }

现在,先用前面搜到的例子进行测试:

 1  ///
 2  /// @file    Student.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:51:42
 5  ///
 6
 7 #include "Proxy.h"
 8 #include "Tickets.h"
 9
10 using namespace marrs;
11
12 int main()
13 {
14     Tickets * ticket = new Tickets("bus_ticket");
15     ticket->Price();
16     ticket->Selling();
17
18     Proxy * proxy = new Proxy(ticket);
19     proxy->Price();
20     proxy->Selling();
21     delete proxy;
22
23     proxy = ticket->Get_Proxy();
24     proxy->Price();
25     proxy->Selling();
26     delete proxy;
27
28     delete ticket;
29
30     return 0;
31 }

编译,运行:

[[email protected] ~/object-oriented/Proxy_Pattern_2]$>g++ * -o main.exe
[[email protected] ~/object-oriented/Proxy_Pattern_2]$>./main.exe
please use proxy
please use proxy
please use proxy
please use proxy
price: 100 RMB
sell: bus_ticket

看着像是强制代理了。好,现在修改一下main:

 1  ///
 2  /// @file    Student.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:51:42
 5  ///
 6
 7 #include "Proxy.h"
 8 #include "Tickets.h"
 9
10 using namespace marrs;
11
12 int main()
13 {
14     Tickets * ticket = new Tickets("bus_ticket");
15     Proxy * proxy = ticket->Get_Proxy();
16     Proxy * proxy_other = new Proxy(ticket);
17
18     proxy->Price();
19     proxy->Selling();
20
21     ticket->Price();
22     ticket->Selling();
23
24     proxy_other->Price();
25     proxy_other->Selling();
26
27     delete proxy;
28     delete ticket;
29
30     return 0;
31 }
[[email protected] ~/object-oriented/Proxy_Pattern_2]$>g++ * -o main.exe
[[email protected] ~/object-oriented/Proxy_Pattern_2]$>./main.exe
price: 100 RMB
sell: bus_ticket
price: 100 RMB
sell: bus_ticket
price: 100 RMB
sell: bus_ticket

结果完全符合预期,真实对象也可以使用自己的方法了。甚至乱套了,随便来个代理都可以用了。

于是,我对其进行修改,对判断是不是proxy加了点东西:

version 1:

此方法设置了唯一代理

 1  ///
 2  /// @file    Tickets.h
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:39:17
 5  ///
 6
 7 #ifndef __TICKETS_H__
 8 #define __TICKETS_H__
 9
10 #include "Selling_Tickets.h"
11
12 namespace marrs{
13 class Proxy;
14 class Tickets
15 : public SellingTickets
16 {
17     public:
18         Tickets(string ticket_type);
19         ~Tickets();
20     public:
21         void Selling(Proxy * proxy);
22         void Price(Proxy * proxy);
23
24     private:
25         void Selling();
26         void Price();
27
28     public:
29         Proxy * Get_Proxy();
30
31     private:
32         bool Is_Proxy(Proxy * proxy) const;
33
34     private:
35         string _ticket_type;
36         Proxy * _proxy;
37 };
38
39 }
40
41 #endif // __TICKETS_H__
 1  ///
 2  /// @file    Proxy.h
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:46:13
 5  ///
 6
 7 #ifndef __PROXY_H__
 8 #define __PROXY_H__
 9
10 #include "Selling_Tickets.h"
11
12 namespace marrs{
13 class Tickets;
14 class Proxy
15 : public SellingTickets
16 {
17     public:
18         Proxy(Tickets * ticket);
19
20     public:
21         void Selling();
22         void Price();
23
24     private:
25         Tickets * _ticket;
26
27 };
28
29 }
30
31 #endif // __PROXY_H__
 1  ///
 2  /// @file    Tickets.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-19 14:38:00
 5  ///
 6
 7 #include "Tickets.h"
 8 #include "Proxy.h"
 9
10 namespace marrs{
11
12 Tickets::Tickets(string ticket_type)
13 : _ticket_type(ticket_type)
14 , _proxy(NULL)
15 {
16
17 }
18
19 Tickets::~Tickets()
20 {
21     if(_proxy)
22     {
23         delete _proxy;
24     }
25 }
26
27 void Tickets::Selling(Proxy * proxy)
28 {
29     if(Is_Proxy(proxy))
30     {
31         Selling();
32     }
33 }
34
35 void Tickets::Price(Proxy * proxy)
36 {
37     if(Is_Proxy(proxy))
38     {
39         Price();
40     }
41 }
42
43 void Tickets::Selling()
44 {
45     cout << "sell: " << _ticket_type << endl;
46 }
47
48 void Tickets::Price()
49 {
50     cout << "price: 100 RMB" << endl;
51 }
52
53 Proxy * Tickets::Get_Proxy()
54 {
55     if(!_proxy)
56     {
57         _proxy = new Proxy(this);
58         return _proxy;
59     }
60     return NULL;
61 }
62
63 bool Tickets::Is_Proxy(Proxy * proxy) const
64 {
65     if(proxy != _proxy)
66     {
67         cout << "please use proxy" << endl;
68         return false;
69     }
70     return true;
71 }
72
73 }
 1  ///
 2  /// @file    Proxy.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-19 14:52:18
 5  ///
 6
 7 #include "Proxy.h"
 8 #include "Tickets.h"
 9
10 namespace marrs{
11
12 Proxy::Proxy(Tickets * ticket)
13 : _ticket(ticket)
14 {
15 }
16
17 void Proxy::Selling()
18 {
19     _ticket->Selling(this);
20 }
21
22 void Proxy::Price()
23 {
24     _ticket->Price(this);
25 }
26
27 }
 1  ///
 2  /// @file    Student.cc
 3  /// @author  marrs([email protected])
 4  /// @date    2017-08-13 20:51:42
 5  ///
 6
 7 #include "Proxy.h"
 8 #include "Tickets.h"
 9
10 using namespace marrs;
11
12 int main()
13 {
14     Tickets * ticket = new Tickets("bus_ticket");
15     Proxy * proxy = ticket->Get_Proxy();
16
17     proxy->Price();
18     proxy->Selling();
19
20     Proxy * proxy_other = new Proxy(ticket);
21     proxy_other->Price();
22     proxy_other->Selling();
23
24     ticket->Price(proxy);
25     ticket->Selling(proxy);
26
27     ticket->Price(proxy_other);
28     ticket->Selling(proxy_other);
29
30     delete proxy_other;
31     delete ticket;
32
33     return 0;
34 }
 1 [[email protected] ~/object-oriented/Proxy_Pattern_3]$>g++ *.h *.cc -o main.exe
 2 [[email protected] ~/object-oriented/Proxy_Pattern_3]$>./main.exe
 3 price: 100 RMB
 4 sell: bus_ticket
 5 please use proxy
 6 please use proxy
 7 price: 100 RMB
 8 sell: bus_ticket
 9 please use proxy
10 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都是我自己瞎想的....虽能实现,但是不知道是否实用。

时间: 2025-01-15 19:48:34

设计模式学习——代理模式(Proxy Pattern)之 强制代理(强校验,防绕过)的相关文章

设计模式 - 代理模式(proxy pattern) 未使用代理模式 详解

代理模式(proxy pattern) 未使用代理模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 部分代码参考: http://blog.csdn.net/caroline_wendy/article/details/37698747 如果需要监控(monitor)类的某些状态, 则需要编写一个监控类, 并同过监控类进行监控. 但仅仅局限于本地, 如果需要远程监控, 则需要使用代理模式(proxy pattern). 具体方法: 1. 类中需要提供

设计模式之代理模式---Proxy Pattern

模式的定义 代理模式(Proxy Pattern)也叫做委托模式,定义如下: Provide a surrogate or placeholder for another object to control access to is. 为其他对象提供一种代理以控制对这个对象的访问. 类型 结构类 模式的使用场景 想想现实世界中,打官司为什么要找个律师?因为你不想参与中间过程的是是非非,只要完成自己的工作就可以,其它的事情比如事前调查,事后追查都可以由律师来负责,这就可以减少你的负担.代理模式使用

设计模式(结构型)之代理模式(Proxy Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(结构型)之享元模式(Flyweight Pattern)>http://blog.csdn.net/yanbober/article/details/45477551 概述 代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个

二十三种设计模式[12] - 代理模式(Proxy Pattern)

前言 代理模式,属于对象结构型模式.在<设计模式 - 可复用的面向对象软件>一书中将之描述为" 为其它对象提供一种代理以控制对这个对象的访问 ". 在代理模式中,通常使用一个类来代表另一个类的功能,并由这个代理对象去控制原对象的引用. 结构 Subjuet(公共接口):代理类和被代理类的公共接口,保证任何使用目标的地方都可以被代理类替换: RealSubject(被代理类):代理类所代表的目标类: Proxy(代理类):包含对目标类的引用,目标类的封装: 场景 在日常生活中

设计模式之(二)---代理模式Proxy Pattern

什么是代理模式呢?我很忙,忙的没空理你,那你要找我呢就先找我的代理人吧,那代理人总要知道 被代理人能做哪些事情不能做哪些事情吧,那就是两个人具备同一个接口,代理人虽然不能干活,但是被 代理的人能干活呀. 比如西门庆找潘金莲,那潘金莲不好意思答复呀,咋办,找那个王婆做代理,表现在程序上时这样的: 先定义一种类型的女人(接口): package com.fc.Proxy; public interface KindWoman { public void makeEyesWithMan(); //抛媚

代理模式(Proxy Pattern)

一.概述在软件开发中,有些对象由于创建成本高.访问时需要与其它进程交互等原因,直接访问会造成系统速度慢.复杂度增大等问题.这时可以使用代理模式,给系统增加一层间接层,通过间接层访问对象,从而达到隐藏系统复杂性.提高系统性能的目的.二.代理模式代理模式为其他对象提供一种代理以控制对这个对象的访问.其结构图如下: Subject定义了RealSubject和Proxy共用的接口,使得在任何使用RealSubject的地方都可以使用Proxy abstract class Subject { publ

设计模式 -- 代理模式 (proxy Pattern)

定义: 为其他对象提供一种代理以控制对这个对象的访问: 角色: 1,抽象主题类,(接口或者抽象类),抽象真实主题和代理的共有方法(如下Subject类): 2,具体实现的主题类,继承或者实现抽象主题类的抽象方法(如下RealSubject类): 3,代理类,继承实现抽象主题类,并提供传递具体实现主题类,在实现方法里面调用具体实现的主题类(如下ProxySubject类); Subject.java /** * Created by Administrator on 2016/8/31. */ p

13.代理模式(Proxy Pattern)

using System; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { // 创建一个代理对象并发出请求 Person proxy = new Friend(); proxy.BuyProduct(); Console.Read(); } } // 抽象主题角色 public abstract class Person { public abstract void BuyPro

Android设计模式之代理模式 Proxy

一.概述 代理模式也是平时比较常用的设计模式之一,代理模式其实就是提供了一个新的对象,实现了对真实对象的操作,或成为真实对象的替身.在日常生活中也是很常见的.例如A要租房,为了省麻烦A会去找中介,中介会替代A去筛选房子,A坐享中介筛选的结果,并且交房租也是交给中介,这就是一个典型的日常生活中代理模式的应用.平时打开网页,最先开到的一般都是文字,而图片等一些大的资源都会延迟加载,这里也是使用了代理模式. 代理模式的组成: Abstract Subject:抽象主题-声明真实主题和代理主题共同的接口

设计模式三: 代理模式(Proxy) -- JDK的实现方式

设计模式三: 代理模式(Proxy) -- JDK的实现方式 简介 代理模式属于行为型模式的一种, 控制对其他对象的访问, 起到中介作用. 代理模式核心角色: 真实角色,代理角色; 按实现方式不同分为静态代理和动态代理两种; 意图 控制对其它对象的访问. 类图 实现 JDK自带了Proxy的实现, 下面我们先使用JDK的API来演示代理如何使用, 随后再探究Proxy的实现原理,并自己来实现Proxy. JDK代理类的使用: (InvocationHandler,Proxy) 使用JDK实现的代