设计模式学习笔记(十九:代理模式)

1.1概述

    为其他对象提供一种代理以控制对这个对象的访问。这就是代理模式的定义。

    当用户希望和某个对象打交道,但程序可能不希望用户直接访问该对象,而是提供一个特殊的对象,这个特殊的对象被称作当前用户要访问对象的代理,程序让用户和对象的代理打交道,即让用户通过访问代理来访问想要访问的对象。在代理模式中,代理的特点是:它与所代理的对象实现了相同的接口,也就是说代理和它多代理的对象向用户公开了相同的方法,当用户请求代理调用该方法时,代理可能需要验证某些信息或检查它所代理的对象是否可用,当代理确认它所代理的对象能调用箱通风的方法时,就把实际的方法调用委派给它所代理的对象,即让所代理的对象调用同样的方法。

  例如,公司里的秘书是老板的代理,老板和秘书都有听电话的方法:herePhone()。公司要求用户必须首先和秘书通电话才能和老板通电话,也就是说,用户必须首先请求秘书调用herePhone(),当秘书确认老板可以接电话时,就将用户的实际请求委派给老板,即让老板调用herePhone()方法。具体类关系如下图一所示:

 

图一:老板和秘书

1.2模式的结构

代理模式包括以下三种角色:

(1)抽象主题(Subject):抽象主题是一个接口,该接口是对象和它的代理所共用的接口,即是RealSubject角色和Proxy角色实例所实现的接口。

(2)实际主题(RealSubject):实际主题是实现抽象主题接口的类。实际主题的实例是代理角色(Proxy)实例所要代理的对象。

(3)代理(Proxy):代理是实现抽象主题接口的类(代理和实际主题实现了相同的接口)。代理含有主题接口声明的变量,该变量用来存放RealSubject角色的实例引用,这样一来,代理的实例就可以控制对它所包含的RealSubject角色的实例访问,即可以控制对它所代理对象的访问。

代理模式结构的类图如下图二所示:

 

图二:代理模式的类图

 

 

1.3代理模式的优点

1)代理模式可以屏蔽用户真正请求的对象,使用户程序和真正的对象之间解耦。

2)使用代理来担当那些创建耗时的对象的替身。

1.4适合使用代理模式的情景

1)程序可能不希望用户直接访问该对象,而是提供一个特殊的对象以控制对当前对象的访问。

2)如果一个对象(例如很大的图像)需要很长时间才能加载完成。

3)如果对象位于远程主机上,需要为用户提供访问该远程对象的能力。

1.5代理模式的使用

以下通过一个简单的问题来描述怎样使用代理模式,这个简单的问题是:用户输入三个代表三角形三边长度的数值,代理对象验证用户输入的三个数值是否能构成三角形,如果能构成三角形,就创建一个三角形对象,并让该三角形对象计算自身的面积。

 首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:

(1)抽象主题(Subject

本问题中,抽象主题角色是Geometry接口,Geometry接口的代码如下:

package com.liuzhen.nineteen_proxy;

public interface Geometry {
    public double getArea();
}

(2)实际主题(RealSubject

对于本问题,实际主题(RealSubject)是Triangle类,代码如下:

package com.liuzhen.nineteen_proxy;

public class Triangle implements Geometry {

    double sideA, sideB, sideC, area;
    
    public Triangle(double a,double b,double c){
        sideA = a;
        sideB = b;
        sideC = c;
    }
    
    public double getArea() {
        double p = (sideA+sideB+sideC)/2.0;
        area = Math.sqrt(p*(p-sideA)*(p-sideB)*(p-sideC));
        return area;
    }

}

(3)代理(Proxy

对于本问题,代理是TriangleProxy类,代码如下:

package com.liuzhen.nineteen_proxy;

public class TriangleProxy implements Geometry {

    double sideA, sideB, sideC;
    Triangle triangle;
    
    public void setABC(double a,double b,double c){
        sideA = a;
        sideB = b;
        sideC = c;
    }
    
    public double getArea() {
        if(sideA+sideB > sideC && sideA+sideC > sideB && sideB+sideC > sideA){
            triangle = new Triangle(sideA,sideB,sideC);
            double area = triangle.getArea();   //让所代理的对象调用getArea()方法
            return area;
        }
        else
            return -1;
    }

}

(4)具体使用

      通过NineteenApplication类来具体实现上述相关类和接口,来实现代理模式的运用,其代码如下:

package com.liuzhen.nineteen_proxy;

import java.util.Scanner;

public class NineApplication {
    
    public static void main(String[] args){
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入三个数,每输入一个数按回车确认:");
        double a, b , c;
        a = reader.nextDouble();
        b = reader.nextDouble();
        c = reader.nextDouble();
        TriangleProxy proxy = new TriangleProxy();
        proxy.setABC(a, b, c);
        double area = proxy.getArea();
        System.out.println("面积是:"+area);
    }
    
}

运行结果:

请输入三个数,每输入一个数按回车确认:
20
20
20
面积是:173.20508075688772

参考资料:

      1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5

 

 

原文地址:https://www.cnblogs.com/liuzhen1995/p/6040884.html