zoukankan      html  css  js  c++  java
  • 代理模式

      一、 引入

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

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

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

  • 相关阅读:
    第四章 方法(4.2 方法的嵌套调用)
    C#利用for循环打印图形练习题
    第三章 C#程序结构 (3.3 循环结构)
    第六章 数组和索引器 (6.6 索引器)
    第五章 类与对象 5.2 猫类(案例二)
    第五章 类与对象 5.1 时间类(案例一)
    第三章 C#程序结构[3.2 选择结构的应用(Windows窗体应用程序)(四)]
    第三章 C#程序结构(3.1 顺序与选择结构)
    第二章 C#语法基础 (2.2 C#语言的运算符和表达式)
    第二章 C#语法基础(2.1C#语言的数据类型二)
  • 原文地址:https://www.cnblogs.com/mo-lu/p/10829129.html
Copyright © 2011-2022 走看看