zoukankan      html  css  js  c++  java
  • 23 DesignPatterns学习笔记:C++语言实现 --- 2.7 Proxy

    23 DesignPatterns学习笔记:C++语言实现 --- 2.7 Proxy

     2016-07-18 

    (www.cnblogs.com/icmzn)


    模式理解

     

     1. Proxy 代理模式
        为其他对象提供一种代理可以间接控制这个对象的访问。
        又称为“委托模式”,其他设计模式也是在代理模式的基础上扩展的,如“策略模式”“状态模式”“访问者模式”,代理模式的特殊应用。
    在Spring的AOP技术,以及Struts的From元素映射就是代理行为。
        一般代理具有多种版本(扩展)如:普通代理模式,强制代理模式,动态代理模式
        一般代理的角色:
        (1)CAbsSubject: 抽象对象,被代理对象的一类的行为,抽象类或者接口。
        (2)Proxy: 代理类,通过组合的方式(has a)拥有一个CabsSubject的指针或者引用,通过将抽象类的接口调用委托被真实对象实现,
        从而可以通过代理控制真实对对象接口的“预处理”“善后处理”工作。代理类必须要是想CAbsSubjecrt接口,这样才能和被代理者保持相似。
        (3)RealSubject: 具体的被代理的对象,具体的业务执行者。

    2. 代理的优点
    (1)职责清晰
        被代理的对象,真实的subject就是实际的业务逻辑,只完成本职责的事物。
    (2)高扩展性
        具体的Subject随时都可能发生变化,只要接口不变,代理类能不变,及时Subject发生变换。
    (3)智能化
        通过“动态代理”,完成智能完成多点接入操作。

    3. 代理的适用场景
        在实际的编程中,代理的应用场景非常多,SpringAOP(面向切面编程)就是一个智能动态代理应用。
    (1)当常见一个大的对象的时候,如创建一个大的图片,可以使用代理来完成创建的过程
    (2)为网络上的一个对象创建一个局部的本地代理,我们将操作网络上对象的过程通过操作本地代理来完成。
    (3)对对象进行不同的权限控制访问的时候,不同权限的用户提供不同的操作权限,把这一控制过程交给代理对象来完成。
    (4)类似于智能指针的操作方法,也使用到了代理思想。
    4. 代理的讨论与扩展

    (1)代理的扩展
     普通代理模式:
        环境只能访问代Proxy角色,而不能访问真实的Subject。即环境不能new 具体的Subject对象,只能通过代理类操作相应的Subject。
        即代理角色管理真实角色,通过代理角色直接操作真实对象。
        (在实际项目中,一般是通过禁止new真实Subect来实现。)
     强制代理模式:
        强制环境必须通过真实角色来查找代理角色,然后才能访问真实角色的属性方法。即不支持直接new CrealSubject,以及不允许new CProxy
        都不能访问。强制使用CRealSubject指定的CProx类才能访问。即真实角色管理代理类。在CabsSubject中添加getProxy()方法,返回指定的代理对象。
        并在真实对象实现的方法中进行检测代理对象是否有效来判定限制。
    有个性的代理类:
        代理类Proxy不仅可以实现CAbsSubject接口,而且也可以实现其他不同的接口,通过对CRealSubject的借口进行“过滤”拦截,从而增强CRealSubject。
        也可以组合其他真实的角色,这种情况下,代理类的职责并不一定单一。增强CrealSubject的预处理、过滤过滤消息、消息转发、事后处理消息。
     动态代理模式:
        定义,实现阶段并不关心代理的对象是谁,而是在运行阶段才指定哪一个对象。前面自己写代理类的属于“静态代理类”。
        AOP(Aspect Oriented Programming)核心思想就是采用了动态代理机制。在Java语言环境下可以提供动态代理接口InvocationHandler。
        AOP编程,对于我们的日志、事物、权限等都可以在系统设计阶段不用考虑,而在设计之后通过AOP贬称该技术方法,简单实现负责的作用。
        动态代理是代理的职责,是一个通用类,不具有业务意义。具体的CRealsubject实现相关的逻辑功能,二者之间没有相互耦合的关系。


     程序实现(C++)

     Proxy.h

      1 #pragma once
      2 #include <iostream>
      3 
      4 using namespace std;
      5 
      6 /*
      7     1.0 最简化的proxy类型结构
      8     (1)CAbsSubject类抽象接口
      9     (2)CRealSubject , CProxy都要实现CAbsSubject接口,这样二者维持相似
     10     (3)CProxy 组合拥有一个CAbsSubject的引用或者指针,通过此指针完成对真实实现的预处理以及售后处理。
     11 */
     12 class CAbsSubject
     13 {
     14 public:
     15     virtual void methodInvoke() = 0;
     16 };
     17 
     18 class CRealSubject :public CAbsSubject
     19 {
     20 public:
     21     void methodInvoke() override
     22     {
     23         cout << "实际对象调用方法执行中..." << endl;
     24     }
     25 
     26 };
     27 
     28 class CProxy : public CAbsSubject
     29 {
     30 public:
     31     CProxy(CAbsSubject* p) :m_pSubject(p){};
     32     //不释放被代理的对象
     33     ~CProxy(){};
     34     void methodInvoke() override
     35     {
     36         cout << "对象预处理...." << endl;
     37         m_pSubject->methodInvoke();//真实调用的实现部分
     38         cout << "对象善后处理...." << endl;
     39     }
     40 
     41 private:
     42     CAbsSubject* m_pSubject;
     43 };
     44 
     45 /*
     46     1.1A 代理扩展:普通代理模式框架A
     47     环境只能访问代Proxy角色,而不能访问真实的Subject。即环境不能new 具体的Subject对象,只能通过代理类操作相应的Subject。
     48     (在代理内部实现真实Subject的创建,然后在真实Subject的沟站函数传入表示病判断)
     49     //或者直接将CRealSubject类构造声明为Protect:即可,但是太绝对
     50 */
     51 
     52 class CAbsSubjectA
     53 {
     54 public:
     55     virtual void methodInvoke() = 0;
     56 
     57 };
     58 
     59 class CRealSubjectA : public CAbsSubjectA
     60 {
     61 public:
     62     CRealSubjectA(CAbsSubjectA* p = nullptr)
     63     {
     64         if (!p)
     65             throw "不能直接创建具体Subject使用,请借助于派生类...";
     66         
     67     }
     68     void methodInvoke() override
     69     {
     70         cout << "实际对象调用方法执行中..." << endl;
     71     }
     72 
     73 };
     74 
     75 class CProxyA : public CAbsSubjectA
     76 {
     77 public:
     78     CProxyA()
     79     {
     80         m_pSubject = new CRealSubjectA(this);
     81     }
     82     ~CProxyA()
     83     {
     84         delete m_pSubject;
     85     }
     86     //如果不继承基累的virtual纯虚拟方法,则不能创建对象this;
     87     void methodInvoke() override
     88     {
     89         cout << "对象预处理...." << endl;
     90         m_pSubject->methodInvoke();//真实调用的实现部分
     91         cout << "对象善后处理...." << endl;
     92     }
     93 
     94 private:
     95     CAbsSubjectA* m_pSubject;
     96 };
     97 
     98 /*
     99 1.1B 代理扩展:强制代理模式框架A
    100 强制环境必须通过真实角色来查找代理角色,然后才能访问真实角色的属性方法。即不支持直接new CrealSubject,以及不允许new CProxy
    101 都不能访问。强制使用CRealSubject指定的CProx类才能访问。即真实角色管理代理类。在CabsSubject中添加getProxy()方法,返回指定的代理对象。
    102 并在真实对象实现的方法中进行检测代理对象是否有效来判定限制。
    103     只要CRealSubject的getprox()没有调用,则成员一致为空,则方法就不能调用,所以必须在CREalSubject中的方法中进行代理类判定。
    104 */
    105 
    106 class CAbsSubjectB
    107 {
    108 public:
    109     virtual void methodInvoke() = 0;
    110     virtual CAbsSubjectB* getTheProxy() = 0;
    111 };
    112 
    113 class CProxyB : public CAbsSubjectB
    114 {
    115 public:
    116     //代理特定的对象
    117     CProxyB(CAbsSubjectB* p)
    118     {
    119         m_pSubject = p;
    120     }
    121     //只使用,不清楚管理的指针
    122     ~CProxyB()
    123     {
    124     }
    125     //如果不继承基累的virtual纯虚拟方法,则不能创建对象this;
    126     void methodInvoke() override
    127     {
    128         cout << "对象预处理...." << endl;
    129         m_pSubject->methodInvoke();//真实调用的实现部分
    130         cout << "对象善后处理...." << endl;
    131     }
    132     //必须实现--没有意义
    133     CAbsSubjectB* getTheProxy()
    134     {
    135         return this;
    136     }
    137 private:
    138     CAbsSubjectB* m_pSubject;
    139 };
    140 
    141 //智能使用真实对象指定的带来执行
    142 class CRealSubjectB : public CAbsSubjectB
    143 {
    144 public:
    145     CRealSubjectB()
    146     {
    147         m_pProxy = nullptr;
    148     }
    149     void methodInvoke() override
    150     {
    151         if (isValidateProx())
    152         {
    153             //管理指定的具体对象的代理
    154             cout << "实际对象调用方法执行中..." << endl;
    155         }
    156         else
    157         {
    158             throw "强制使用(1)CrelSubject指定的(2)Cproxy对象调用...两个条件限制";
    159         }
    160     }
    161     //此方法不调用,m_pProxy永远为nullptr,则其方法永远不能调用
    162     CAbsSubjectB* getTheProxy()
    163     {
    164         m_pProxy = new CProxyB(this);
    165         return m_pProxy;
    166     }
    167 
    168 private:
    169     bool isValidateProx()
    170     {
    171         if (m_pProxy)
    172             return true;
    173         else
    174             return false;
    175     }
    176 private:
    177     CAbsSubjectB* m_pProxy;
    178 };
    179 
    180 /*
    181 1.1B 代理扩展:C++实现动态代理机制实现???
    182 */

    (1)模板应用

     main.cpp

     1 // Proxys.cpp : 定义控制台应用程序的入口点。
     2 //
     3 
     4 #include "stdafx.h"
     5 #include <iostream>
     6 
     7 #include "ProxyDef.h"
     8 using namespace std;
     9 
    10 
    11 int _tmain(int argc, _TCHAR* argv[])
    12 {
    13 
    14     cout << "--------------------简单框架" << endl;
    15     CAbsSubject* p = new CRealSubject();
    16     CProxy* pProxy = new CProxy(p);
    17     pProxy->methodInvoke();
    18 
    19 
    20     cout << "--------------------普通代理类型框架:只允许使用代理类" << endl;
    21     try
    22     {
    23         CAbsSubjectA* pA = new CRealSubjectA();
    24 
    25     }
    26     catch (const char* error_c)
    27     {
    28         cout << "Error catched! ; " << error_c << endl;
    29 
    30     }
    31 
    32     CProxyA* pProxA = new CProxyA();
    33     pProxA->methodInvoke();
    34 
    35 
    36     cout << "--------------------强制代理框架:只允许使用CRealSubject" << endl;
    37     try
    38     {
    39         CAbsSubjectB* pB = new CRealSubjectB();
    40         CProxyB* pProxyB = new CProxyB(pB);
    41         //直接另外新建代理调用
    42         pProxyB->methodInvoke();
    43 
    44     }
    45     catch (const char* error_c)
    46     {
    47         cout << "Error catched! ; " << error_c << endl;
    48 
    49     }
    50 
    51     try
    52     {
    53         CAbsSubjectB* pB = new CRealSubjectB();
    54         //对象调用
    55         pB->methodInvoke();
    56 
    57     }
    58     catch (const char* error_c)
    59     {
    60         cout << "Error catched! ; " << error_c << endl;
    61 
    62     }
    63     //正常调用
    64     CRealSubjectB* pRealB = new CRealSubjectB();
    65     CAbsSubjectB* pB = pRealB->getTheProxy();
    66     pB->methodInvoke();
    67 
    68     cout << "--------------------动态代理框架" << endl;
    69 
    70     system("pause");
    71     return 0;
    72 }

    (2)输出展示

     

     

  • 相关阅读:
    js 基础(面试前必看)
    typescript 使用的几种情况
    flutter 命令卡主的问题
    React 通过注释自动生成文档
    jest 测试入门(一)
    react hooks 全面转换攻略(三) 全局存储解决方案
    缓存穿透、击穿、雪崩区别和解决方案
    java8 lambda表达式
    maven中snapshot快照库和release发布库的区别和作用
    初识 Nacos 以及安装
  • 原文地址:https://www.cnblogs.com/icmzn/p/5697483.html
Copyright © 2011-2022 走看看