欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-10-05 19:34:44
代理模式的本质是一个中间件,主要目的是解耦合服务提供者和使用者。使用者通过代理间接的访问服务提供者,便于后者的封装和控制。是一种结构性模式。 1.目的 为外部调用者提供一个访问服务提供者的代理对象。 2.动机 限制对目标对象的直接访问,降低耦合度。 3.优缺点 优点: 优点: 低耦合 易扩展 灵活度 ......

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

1.目的

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

2.动机

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

3.优缺点

优点:

优点: 

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

缺点:

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

4.分类

  • 静态代理
  • 动态代理

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

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

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

5.主要用途

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

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

6.原理

下面是gof介绍典型的代理模式uml类图

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

subject:

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

realsubject:

 真正的目标对象。

proxy:

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

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

7.实现

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

网络代理

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

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

定义公共接口类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!");
        }
    }
}

 被引用对象类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
        
    }
}

 参考:

gof《design patterns: elements of reusable object-oriented software》

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