代理模式

  一、 引入

  日常生活中我们经常会经常见到中介、婚姻介绍所、代购等,作为中间代理人代办某项事务。在代理过程中会涉及到一件事情(目前由代理机构正在代办)、真正需要办理业务的一方和代理业务一方。例如,小王通过中介买房,这一过程涉及角色包括,具体主题对象(小王)、代理对象(中介)。我们要实现的动作是从房地中心买房,如何确保中介和小王都会进行买房的动作呢?为了保持具体对象和代理对象行为的一致性,我们引入抽象对象(接口),代理对象和真实主题对象均实现该接口。通过代理类中间层,有效控制了委托类对象(小王、小李等想要买房的人)对房产中心的直接访问,解耦了两个类的直接通信。又如有时程序中临时变量赋值,客户端调用web服务,电脑快捷方式作为应用程序的代理都是代理的实际应用,在日常业务中随处可见,具有重要作用。

二、定义

  为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

三、场景应用及实现

  场景描述:男生B1追女生G,通过另一位男生B2传递情书、鲜花等动作,最终B2与G在一起。

  分析:该场景中设计3类对象,分别为追求者B1,B2,被追求者G。实现的方法包括送情书、送鲜花等;

3.1 没有代理的代码

3.1.1 结构图

3.1.2 代码实现

class Girl
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Girl(string name,int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
 class Pursuite
    {
        Girl girl;
        public Pursuite(Girl _girl){
            this.girl=_girl;
        }
        public void sendFlowers()
        {
            Console.Write(girl.Name+"give you flowers");
        }
        public void sendDolls()
        {
            Console.Write(girl.Name + "give you dolls");
        }
        public void sendChoclate()
        {
            Console.Write(girl.Name + "give you choclates");
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
            Girl girl = new Girl("Mary",18);
            Pursuite b1 = new Pursuite(girl);// 然而,B1与girl并不认识
            b1.sendChoclate();
            b1.sendDolls();
            b1.sendFlowers();
            Console.Read();
        }
    }

上述代码实现中,B1与girl直接接触,并未通过“代理“B2进行追求。

3.2 优化——只有代理的代码

3.2.1 结构图

3.2.2 代码实现

 class Proxy
    {
        Girl girl;
        public Proxy(Girl _girl)
        {
            this.girl = _girl;
        }
        public void sendFlowers()
        {
            Console.Write(girl.Name + "give you flowers");
        }
        public void sendDolls()
        {
            Console.Write(girl.Name + "give you dolls");
        }
        public void sendChoclate()
        {
            Console.Write(girl.Name + "give you choclates");
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            Girl girl = new Girl("Mary",18);
            //Pursuite b1 = new Pursuite(girl);// 然而,B1与girl并不认识
            Proxy b2 = new Proxy(girl);
            b2.sendChoclate();
            b2.sendDolls();
            b2.sendFlowers();
            Console.Read();
        }
    }

此时,代码中只有代理者B2和被追求者,要求代理的B1没有出现。场景中B1与B2均存在,且礼物虽然是B2送的,但是由B1买的,那么如何证明呢?

场景业务应该是:B1通过B2将礼物送给Girl。而追求者B1与Girl有相似的地方,B1送礼物,Girl接受礼物,实现的为同一个方法。因此,可以抽象为实现同一个接口。

3.3  优化——符合实际的代码

3.3.1 结构图

3.3.2 代码实现

class Girl
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Girl(string name,int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
interface IGiveGift
    {
        void sendFlowers();
        void sendDolls();
        void sendChoclate();
    }
class Proxy:IGiveGift
    {
        Pursuite pursuite;
        public Proxy(Girl girl)
        {
            pursuite = new Pursuite(girl);
        }
        public void sendFlowers()
        {
            pursuite.sendFlowers();
        }
        public void sendDolls()
        {
            pursuite.sendDolls();
        }
        public void sendChoclate()
        {
            pursuite.sendChoclate();
        }
        
    }
class Pursuite:IGiveGift
    {
         Girl girl;
         public Pursuite(Girl _girl)
        {
            this.girl = _girl;
        }
        public void sendFlowers()
        {
            Console.Write(girl.Name + "give you flowers");
        }
        public void sendDolls()
        {
            Console.Write(girl.Name + "give you dolls");
        }
        public void sendChoclate()
        {
            Console.Write(girl.Name + "give you choclates");
        }
        
    }
class Program
    {
        static void Main(string[] args)
        {
            Girl girl = new Girl("小小",18);
            Proxy proxy = new Proxy(girl);
            proxy.sendChoclate();
            proxy.sendDolls();
            proxy.sendFlowers();
        }
    }

此时,girl与代理proxy直接接触,但接受到的确实追求者B1送的礼物。

 4、代理模式的结构

   代理模式的核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层,代理模式结构如下图所示:

 

  代理模式包含3个角色:

  • 抽象角色,声明真实主题和代理主题的共同接口,通过接口或抽象类声明真实角色实现的业务方法。
  • 代理角色:实现抽象角色,是真实角色的代理,并调用目标对象。内部包含有对真实主题的引用,从而可以在任何时候操作真实主题对象;代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候代替真实主体;控制真实主题的应用,负责在需要的时候创建主题对象(或创建真实主题对象)。代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的将调用传递给真实主题对象。
  • 真实角色:代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。

 5. 代理模式的优缺点

  优点:(1)职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。(2)代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。(3)高扩展性。

  缺点:由于在客户端和真实主题之间增加了一个代理对象,所以会造成请求的处理速度变慢实现代理类也需要额外的工作,从而增加了系统的实现复杂度,比如说远程代理。

注: 代理类和委托类必须实现同一个接口,因为代理真正调用的业务逻辑是在委托类中实现的。

原文地址:https://www.cnblogs.com/mo-lu/p/10829129.html