• 代理模式


    直接与间接:
       人们对复杂的软件系统常有一种处理手法,即增加一层间接层,从而对系统获得一种更为灵活、
    满足特定需求的解决方案。    

     动机(Motivate):
        在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。

        如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
    意图(Intent):
           为其他对象提供一种代理以控制对这个对象的访问。  -------《设计模式》GOF

    生活中的例子:
           代理模式提供一个中介以控制对这个对象的访问。一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。

     代码实例:
        在软件系统 中,我们无时不在跨越障碍,当我们访问网络上一台计算机的资源时,我们正在跨越网络障碍,当我们去访问服务器上数据库时,我们又在跨越数据库访问障碍,同 时还有网络障碍。跨越这些障碍有时候是非常复杂的,如果我们更多的去关注处理这些障碍问题,可能就会忽视了本来应该关注的业务逻辑问题,Proxy模式有助于我们去解决这些问题。我们以一个简单的数学计算程序为例,这个程序只负责进行简单的加减乘除运算:

    如果我们想访问远程计算机的时候,一些比较耗时的操作,我们可能不需要同步进行,或者需要进行其他的操作,如果我们每次调用的时候都写出来,代码将十分混乱。

      #region 要访问的远程计算机中的类
        public class ProcessControlComputer
        {
            public void Send(string message)
            {
                //通过此远程计算机发送给指定的人的操作
                //...
                Console.WriteLine(message+":发送成功");
            }
        }
        #endregion

     使用代理,解决这种耗时的操作,这里拿线程举例子

     #region 代理者
        public class Proxy
        {
            private ProcessControlComputer _processcontrolcomputer = new ProcessControlComputer();
    
            public void Send(string message)
            {
                Task.Run(()=> { _processcontrolcomputer.Send(message); });//使用线程操作耗时且无需返回值的远程操作
            }
        }
        #endregion
     static void Main(string[] args)
            {
                ProcessControlComputerProxy p = new ProcessControlComputerProxy();
                p.Send("代理者发送消息");
                Console.WriteLine("正常执行");
                Console.ReadKey();
            }

    为了保证代理与远程类保持相同的方法,这里我们引出一个接口,让其分别实现(下方代码在Program写Send是为因为如果不这样在这里加个休眠,连续执行Send,会使得内部实例化的都是第二个Send),具体代码如下,要好好体会

    为了更大的扩展,杰杰也引入了泛型,好好体会代码...

     #region 保持统一的接口
        public interface IControl
        {
            void Send<T>(string message) where T : IControl, new();
        }
        #endregion
      #region 代理者
        public class Proxy : IControl
        {
            private IControl _processcontrolcomputer;
    
            public void Send<T>(string message) where T : IControl, new()
            {
                _processcontrolcomputer = new T();//只要保证本次的这个实例是对的,就可以(连续执行可能会使得到第一次的该处还没执行,替换成第二处的,这个通过在上方Program中加Send方法,中加休眠来解决)
                Task.Run(() => { _processcontrolcomputer.Send<T>(message); });//使用线程操作耗时且无需返回值的远程操作
            }
        }
        #endregion
     #region 要访问的远程计算机中的类
        public class ProcessControlComputer : IControl
        {
            public void Send<T>(string message) where T : IControl, new()
            {
                //通过此远程计算机发送给指定的人的操作
                //...
                Console.WriteLine(message + ":发送成功到1");
            }
        }
        public class ProcessControlComputer2 : IControl
        {
            public void Send<T>(string message) where T : IControl, new()
            {
                //通过此远程计算机发送给指定的人的操作
                //...
                Console.WriteLine(message + ":发送成功到2");
            }
        }
        #endregion
     class Program
        {
            static void Main(string[] args)
            {
                Proxy p = new Proxy();
                Program program = new Program();
                program.Send<ProcessControlComputer>(p, "代理者发送消息");
                program.Send<ProcessControlComputer2>(p, "发发发");
                Console.WriteLine("正常执行");
                Console.ReadKey();
            }
            private void Send<T>(Proxy p, string message) where T : IControl, new()
            {
                p.Send<T>(message);//只要保证不要同时调用Send即可,给一个小小的时间间隔
                Thread.Sleep(30);
            }
        }

    加油!

  • 相关阅读:
    程序、进程、线程区别与联系
    SQL常用知识与必须掌握的面试常问SQL语句
    快速搭建一个基于react的项目
    原生js判断设备类型
    在vue项目中设置BASE_URL
    纯前端实现数据导出excel文件
    原生js实现拖拽功能
    使用Echarts实现折线图的一点总结
    在vue项目中显示实时时间(年月日时分秒)
    在vue项目中使用MD5.js
  • 原文地址:https://www.cnblogs.com/ningxinjie/p/12199895.html
Copyright © 2020-2023  润新知