• 设计模式之代理模式(proxy pattern)


    代理模式的本质是一个中间件,主要目的是解耦合服务提供者和使用者。使用者通过代理间接的访问服务提供者,便于后者的封装和控制。是一种结构性模式。

    1.目的

    为外部调用者提供一个访问服务提供者的代理对象。

    2.动机

    限制对目标对象的直接访问,降低耦合度。

    3.优缺点

    优点: 

    • 低耦合
    • 易扩展
    • 灵活度高

    缺点:

    • 间接访问可能会延迟请求相应
    • 增加工作量

    4.分类

    • 静态代理
    • 动态代理

      代理类本身的实现可能并不简单,加上每一个需要代理的对象均均需要实现一个代理类,其工作量本身比较大,易出错。

      所谓动态代理(DynamicProxy)是指在程序运行时动态的生成对目标对象的访问接口。

      本文主要介绍前者,关于后者可以参考JDK自带的动态代理。

    5.主要用途

    代理模式在以下场景比较适用:

         1、远程代理。 2、虚代理。 3、保护代理。4、智能指引代理。5、写时复制(Copy-on-Write)代理。  6、缓存代理。 7、防火墙代理。 8、同步化代理。

    6.原理

    下面是GoF介绍典型的代理模式UML类图

    Subject:

     定义RealSubject对外的接口,且这些接口必须被Proxy实现,这样外部调用proxy的接口最终都被转化为对realsubject的调用。

    RealSubject:

     真正的目标对象。

    Proxy:

     目标对象的代理,负责控制和管理目标对象,并间接地传递外部对目标对象的访问。

    1. Remote Proxy: 对本地的请求以及参数进行序列化,向远程对象发送请求,并对响应结果进行反序列化,将最终结果反馈给调用者;
    2. Virtual Proxy: 当目标对象的创建开销比较大的时候,可以使用延迟或者异步的方式创建目标对象;
    3. Protection Proxy: 细化对目标对象访问权限的控制;

    7.实现

     下面我们使用两个例子来实际体验一下代理模式的应用

    网络代理

    对于一些国内不能直接访问的网站,合法的使用的网络代理可以实现对目标网站的访问;

    定义公共接口类Server:

    public interface Server{
        void visit(String url);
    }

      代理服务器ProxyServer:

    public class ProxyServer implements Server{
     
       private RealServer realServer;
     
       public ProxyServer(String serverName){
          this.realServer = new RealServer(serverName);
       }
     
       @Override
       public void visit(String url) {
          realServer.visit(url);
       }
    }

      目标服务器RealServer:

    public class RealServer implements Server {
        private String serverName;
        public RealServer(String serverName) {
            this.serverName = serverName;
            System.out.println("This is " + serverName);
        }
        
        @Override
        public void visit(String url) {
            response(url);
        }
        
        private void response(String res) {
            System.out.println("This is response of " + res + " from server:" + serverName);
        }
    }

     演示:

    public class Demo {
        public static void main(String[] args) {
            Server server = new ProxyServer("www.google.com");
            server.visit("map.google.com");
        }
    }

    智能指针引用计数

    下面使用代理模式简单的模拟指针引用计数问题

    接口类Obj:

    public interface Obj{
        void GetAttr();
        Obj copy();
        void delete();
    }

      智能指针类SmartPointer:

    public class SmartPointer implements Obj{
     
       private RealObj realObj;
       private int counter = 1;
     
       public SmartPointer(String objType){
          this.realObj = new RealObj(objType);
       }
       
       @Override
       public void GetAttr() {
           if(counter > 0) {
               realObj.GetAttr();
           }
           System.out.println("Smart Ref: " + counter);
       }
           
        public Obj copy() {
            if(counter > 0) {
                counter += 1;
                return this;
            }
            System.out.println("Invalid Pointer!");
            return null;
        }
        
        public void delete() {
            if(counter > 0) {
                counter -= 1;
                if(0 == counter) {
                    realObj = null;
                }
            }
            else {
                System.out.println("Invalid Pointer!");
            }
        }
    }
    View Code

     被引用对象类RealObj:

    public class RealObj implements Obj {
        private String objType;
        public RealObj(String objType) {
            this.objType = objType;
            System.out.println("Create Obj: " + objType);
        }
        
        @Override
        public void GetAttr() {
            System.out.println("get attr of real obj " + objType);
        }
    
        @Override
        public Obj copy() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void delete() {
            // TODO Auto-generated method stub
            
        }
    }
    View Code

     参考:

    GoF《Design Patterns: Elements of Reusable Object-Oriented Software》

    https://www.runoob.com/design-pattern/proxy-pattern.html

  • 相关阅读:
    React学习 之 阶段性小作品(待办事项_已完成事项 CRUD)
    React 学习之 键盘事件 表单事件 事件对象以及React中的ref获取dom节点 、React实现类似Vue的双向数据绑定
    mysql 时间戳 今天 昨天 7天 30天 及未来时间
    mysql历史数据自动归档
    配置nginx支持跨域访问
    AWK 简明教程
    shell 生成指定范围随机数与随机字符串
    Linux下Shell的for循环语句
    系统部署安装工具 WinToHDD Enterprise v4.2
    格式工厂 FormatFactory v5.1.0.0
  • 原文地址:https://www.cnblogs.com/yssjun/p/10889022.html
Copyright © 2020-2023  润新知