• 设计模式之代理模式(十)


    一、引出模式

    代理,在生活我我们非常常见。比如在中学时期,总追过女孩子吧!身为码农的我们,没追过也没关系,总看过别人追过女孩子吧!这里出现了3个重要人物,甲想追求乙,但甲又不认识乙,幸好乙的闺蜜丙是甲的小学同学,于是呢,甲就通过丙给乙传递一些纸条,情书之类的。在这里面同学丙就充当着一个代理的角色,甲无法直接找到乙说话,只能通过丙给乙传递消息。

    二、认识模式

    1.定义:

    代理模式为目标对象提供一种代理,并由该代理对象控制对这个目标对象的访问。

    2.模式结构和说明

    Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何地方使用具体目标对象的地方使用代理对象。

    RealSubject:具体的目标对象,真正实现目标接口的功能。

    Proxy:代理对象,主要有如下功能:

    * 实现和具体的目标对象一样的接口,这样可以使用代理来代替具体的目标对象

    * 保存一个指向具体目标对象的引用,可以在需要时调用具体的目标对象。

    * 可以控制对具体目标对象的访问,并可以负责创建和删除它。

    3.示例代码

     class Program
        {
            static void Main(string[] args)
            {
                Subject subject = new Proxy(new RealSubject());
                subject.Request();
     
                Console.ReadKey();
            }
        }
     
        /// <summary>
        /// 定义具体的目标对象和代理公有接口
        /// </summary>
        public abstract class Subject
        {
            public abstract void Request();
        }
     
        /// <summary>
        /// 具体的目标对象,是真正被代理的对象
        /// </summary>
        public class RealSubject : Subject
        {
            public override void Request()
            {
                //执行真正要实现的功能
                Console.WriteLine("调用真实对象");
            }
        }
     
        /// <summary>
        /// 代理对象
        /// </summary>
        public class Proxy : Subject
        {
            //持有被代理的具体目标对象
            private RealSubject subject = null;
     
            //注入具体被代理的目标对象
            public Proxy(Subject subject)
            {
                this.subject = (RealSubject) subject;
            }
     
            public override void Request()
            {
                //转调之前可以做一些事情,比如权限判断等
     
                //转调具体目标对象的方法
                subject.Request();
     
                //转调之后也可以做一些事情
            }
        }

    三、理解模式

    1.模式功能:

    代理模式通过创建一个代理对象,用这个对象去代表真实对象,当客户端操作这个给代理对象时,实际上功能最终还是会有真实对象来实现,只不过是通过代理操作的。

    正是因为代理对象夹在客户端与真实对象之间,相当于中转站,所以在中转前后可以做很多事情,比如权限判断。

    2.代理分类:

    * 远程代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程代理又叫做大使(Ambassador)。

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

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

    * 保护代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。

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

    * 防火墙代理:保护目标,不让恶意用户接近。

    * 同步化代理:使几个用户能够同时使用一个对象而没有冲突。

    * 智能指引:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。

    在所有种类的代理模式中,虚拟(Virtual)代理、远程(Remote)代理、智能引用代理(Smart Reference Proxy)和保护(Protect or Access)代理是最为常见的代理模式。

    3.具体目标对象和代理对象的关系

    从模式图来看,好像一个具体目标类就有一个代理类,其实不是这样的。如果代理类能完全通过接口来操作它所代理的目标对象,那么代理对象就不需要知道具体的目标对象,这样就无需为每一个具体目标对象都创建一个代理类。

    4.保护代理细说

    保护代理是一种控制对原始对象访问的代理,多用于对象应该有不同的访问权限的时候。保护代理会检查调用者是否具有请求所必需的访问权限,如果没有,就不会调用目标对象,从而实现对目标对象的保护。

    示例:现在有个订单系统,一旦订单被创建,那么只有创建人才能需改和删除订单。

    class Program
        {
            static void Main(string[] args)
            {
                #region 保护代理
    
                #endregion
    
                OrderApi orderApi = new ProxyOrder(new Order("设计模式", 100, "zxj"));
                orderApi.SetProductName("哈哈哈", "zxj");
    
                Console.ReadKey();
            }
        }
    
    
        #region 保护代理
    
        /// <summary>
        /// 订单接口
        /// </summary>
        public abstract class OrderApi
        {
            public abstract void SetProductName(string ProductName, string ProductUser);
        }
    
        /// <summary>
        /// 订单
        /// </summary>
        public class Order : OrderApi
        {
            /// <summary>
            /// 产品名称
            /// </summary>
            public string ProductName { get; set; }
    
            /// <summary>
            /// 产品数量
            /// </summary>
            public int ProductNum { get; set; }
    
            /// <summary>
            /// 操作员
            /// </summary>
            public string ProductUser { get; set; }
    
            public Order(string PeoductName, int ProductNum, string ProductUser)
            {
                this.ProductName = PeoductName;
                this.ProductNum = ProductNum;
                this.ProductUser = ProductUser;
            }
    
            public override void SetProductName(string ProductName, string ProductUser)
            {
                throw new NotImplementedException();
            }
        }
    
        public class ProxyOrder : OrderApi
        {
            private Order order;
    
            public ProxyOrder(Order order)
            {
                this.order = order;
            }
    
            public override void SetProductName(string ProductName, string ProductUser)
            {
                if (order.ProductName != null && order.ProductUser.Equals(ProductUser))
                {
                    Console.WriteLine("{0}可以修改", ProductUser);
                }
                else
                {
                    Console.WriteLine("{0}无权修改", ProductUser);
                }
            }
        }
        #endregion

    5.模式特点

    *  远程代理:隐藏了一个对象存在不同的地址空间的事实。

    *  虚代理:可以根据需要创建“大”对象,只要到必须创建对象的时候,虚代理才会创建对象。

    *  保护代理:可以在访问一个对象的前后,附加执行很多操作,除了权限控制之外,还可以进行很多业务,也就是说,可以通过代理来给目标对象增加功能。

    *  智能指引:和保护代理类似,可以在访问一个对象前后附加其他操作,如果存有保护性质的,就算保护代理,其他就算是智能指引。

    6.代理模式的选用

    *  需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理。

    *  需要按照需要创建开销很大的时候,可以使用虚代理。

    *  需要控制原始对象的访问的时候,可以使用保护代理。

    *  需要在访问对象执行一些附加操作的时候,可以使用智能代理。

    7.模式本质 

    控制对象访问

    代理模式通过代理目标对象,把代理对象插入到客户和目标对象之间,从而为客户和目标引入一定的间接性。正是这个间接性,给力代理对象很大的活动空间,可以在目标对象前后,附加很多操作,从而实现新的功能或是扩展。

    从实现哈桑看,代理模式主要使用对象的组合和委托,尤其是在静态代理的实现里面。也可以采用对象继承的方式来实现代理,比如上面的保护代理示例

    8.相关模式

    *  代理模式与适配器模式

    这两个模式有一定的相似性,它们都为另一个对象提供间接性访问,而且都是从自身以外的一个借口想这个对象转发请求。

    但是在功能上,适配器模式主要用来解决接口之间不匹配的问题。它通常是为所适配的对象提供一个不同的接口;而代理模式会实现和目标对象相同的接口。

    *  代理模式和装饰模式

    这两个模式从实现上相似,都是在转掉调其他对象的前后执行一定的功能。

    但是它们的功能和目的是不同的,装饰模式目的是为了让你不生成子类就可以给对象添加指着,也就是为了动态的添加功能;而代理模式的主要目的是控制对对象的访问。

  • 相关阅读:
    从零开始在虚拟机中搭建一个4个节点的CentOS集群(三)-----将一台虚拟机复制成4台虚拟机
    从零开始在虚拟机中搭建一个4个节点的CentOS集群(二)-----在虚拟机中安装Java和Perl
    java后台访问接口
    java文件名更改一直是false,看看是否是文件打开没有关
    java后台调用url无协议
    MyEclipse怎么设置个性化代码注释模板
    sql参数化查询in的参数
    mongodb索引
    oracle分配权限:一个用户访问另一个用户的表
    spring读写分离
  • 原文地址:https://www.cnblogs.com/zxj159/p/3449320.html
Copyright © 2020-2023  润新知