本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7814004.html,记录一下学习过程以备后续查用。

    一、引言

    今天我们要讲结构型设计模式的第七个模式,也是结构型设计模式中的最后一个模式--代理模式。先从名字上来看,“代理”可以理解为“代替”,代替“主人”做一些事情。为什么需要“代理”?是因为某些原因(比如:安全方面的原因),不想让“主人”直接面对这些繁琐、复杂的问题,但是这些事情是经“主人”同意或者授意的,如同“主人”亲自完成的一样。这个模式很简单,生活中的例子也很多。举例说明:歌星、影星的经纪人就是现实生活中一个代理模式的很好例子,还有操作系统中的防火墙,也是代理的例子,要访问系统,先过防火墙这关,否则免谈。还有很多了,就不一一列举了,大家在生活中慢慢地体会吧。

    二、代理模式介绍

    代理模式:英文名称--Proxy Pattern;分类--结构型。

    2.1、动机(Motivate)

    在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者或者系统结构带来很多麻烦。如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。

    2.2、意图(Intent)

    为其他对象提供一种代理以控制对这个对象的访问。——《设计模式》GoF

    2.3、结构图(Structure)

C#设计模式学习笔记:(12)代理模式

    2.4、模式的组成

    代理模式所涉及的角色有三个:

    1)抽象主题角色(Subject):声明了真实主题和代理主题的公共接口,这样一来在使用真实主题的任何地方都可以使用代理主题。

    2)代理主题角色(Proxy):代理主题角色内部含有对真实主题的引用,从而可以操作真实主题对象;代理主题角色负责在需要的时候创建真实主题对象;代理角色通常在将客户端调用传递到真实主题之前或之后,都要执行一些其他的操作,而不是单纯地将调用传递给真实主题对象。

    3)真实主题角色(RealSubject):定义了代理角色所代表的真实对象。

    附:在WCF或者WebService的开发过程中,我们在客户端添加服务引用的时候,在客户程序中会添加一些额外的类,在客户端生成的类扮演着代理主题角色,我们客户端也是直接调用这些代理角色来访问远程服务提供的操作,这个是远程代理的一个典型例子。

    2.5、代理模式的分类

    代理模式按照使用目的可以分为以下几种:

    1)远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是本电脑中,也可以在另一台电脑中。最典型的例子就是--客户端调用Web服务或WCF服务。

    2)虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得对象只在需要时才会被真正创建。

    3)Copy-on-Write代理:虚拟代理的一种,把复制(或者叫克隆)拖延到只有在客户端需要时,才真正采取行动。

    4)保护(Protect or Access)代理:控制一个对象的访问,可以给不同的用户提供不同级别的使用权限。

    5)防火墙(Firewall)代理:保护目标不让恶意用户接近。

    6)智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。

    7)Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以这些结果。

    在上面所有种类的代理模式中,虚拟代理、远程代理、智能引用代理和保护代理较为常见的代理模式。

    2.6、代理模式的具体实现

    说起代理模式,其实很容易,现实生活中的例子也很多。明星的经纪人,国家的发言人都是代理的好例子。

    下面我们就用明星经纪人这个例子来介绍“代理模式”的实现吧。

C#设计模式学习笔记:(12)代理模式
    class Program
    {
        /// <summary>
        /// 该类型就是抽象Subject角色,定义代理角色和真实主体角色共有的接口方法。
        /// </summary>
        public abstract class AgentAbstract
        {
            //该方法执行具体的炒作--该方法相当于抽象Subject的Request方法
            public virtual void Speculation(string thing)
            {
                Console.WriteLine(thing);
            }
        }

        /// <summary>
        /// 该类型是Fan姓明星,有钱有势,想炒什么就炒什么---相当于具体的RealSubject角色
        /// </summary>
        public sealed class FanStar : AgentAbstract
        {
            //有钱有势有背景啊
            public FanStar() { }

            //要有名气,定期要炒作---就是RealSubject类型的Request方法
            public override void Speculation(string thing)
            {
                Console.WriteLine(thing);
            }
        }

        /// <summary>
        /// 该类型是代理类型--相当于具体的Proxy角色
        /// </summary>
        public sealed class AgentPerson : AgentAbstract
        {
            //这是背后的老板
            private readonly FanStar boss;

            //老板在后面发号施令
            public AgentPerson()
            {
                boss = new FanStar();
            }

            //炒作的方法,执行具体的炒作--就是Proxy类型的Request方法
            public override void Speculation(string thing)
            {
                Console.WriteLine("前期弄点绯闻,拍点野照。");
                boss.Speculation(thing);
                Console.WriteLine("然后开发布会,伤心哭泣,继续捞钱。");
            }
        }

        static void Main(string[] args)
        {
            #region 代理模式
            //大明星都有钱,有钱就可以请自己的经纪人。有了经纪人,很多事情就不用自己亲力亲为。
            //弄点绯闻,炒作一下子通过经纪人就可以名正言顺的地操作了,万一搞不好,自己也可以否认。

            //近期,Fan姓明星关注度有点下降,来点炒作。
            AgentAbstract fan = new AgentPerson();
            fan.Speculation("偶尔出来现现身,为炒作造势。");
            Console.WriteLine();

            //过了段时间,又不行了,再炒作一次。
            fan.Speculation("这段时间不火了,开始离婚炒作。");

            Console.Read();
            #endregion
        }
    }
View Code

相关文章: