Java设计模式(四)代理模式详解

一、引言

 

       在实际开发过程中,我们常遇需要到为一个对象在不同的地址空间创建局部代理的情况,比如说一个Web服务器可能被不同的应用使用,我们就需要在每一个应用下都创建一个WEB服务器的局部引用。又或者在创建一些开销很大的对象实例时,就需要使用虚拟代理优化性能。比如打开网页时,网页中的图片总是先先出现图片框,然后在逐渐显示出图片,此时就是用虚拟代理替代了真实的图片,仅存储了图片的路径尺寸等信息。要想实现上功能,就要用到代理模式。


二、模式详解

 

1、模式分析

       代理模式为其他对象提供一种代理以控制对这个对象的访问,它在客户与RealSubject之间设置了一个代理类,客户通过代理类访问RealSubject对象,说白了,就是在客户端中,调用RealSubject中方法的不是RealSubject自己类型的引用,而是通过一个代理类对象的引用调用。

       如图-1所示,在代理模式中,Subject类定义了代理类和RealSubject类的功用方法接口,RealSubject类实现这些具体方法,而在代理类中则维护了一个RealSubject类型的引用,在实现的Subject接口方法中,代理类利用该引用调用RealSubject类的相应方法。而在客户端中,所有对RealSubject类性对象的操作哦都是通过地调用代理类的相关方法实现的,而不是直接对RealSubject类进行调用。


图-1 代理模式UML图

2、具体实现

        我们用一个简单的例子来说明代理模式的具体实现过程。现有一个花心的坏男孩Tom打算同时追两个在不同学校里的女孩Lily和Lucy。追求的手段为送花、娃娃和巧克力,但是这两个女孩根本不认识Tom,而且Tom也很难同时到两个学校给女孩送东西,于是就找了分别在学校1和学校2里的朋友朋友1和朋友2替他去送。我们吧这个例子用Java实现后就是最基本的代理模式。

        首先,我们我们对求爱行为进行了抽象,得到一个LoveAction接口,也就是UML中的抽象Subjiect类。

/**
 * 该类为Subject类, Subject类是从RealSubject和代理类中抽象出来的,从而可以在任何使用
 * RealSubject类的地方使用Proxy类。
 */
interface LoveAction {
    
    public void giveDolls(String girlName);
    public void giveFlower(String girlName);
    public void giveChocolate(String girlName);
    
}/*LoveAction*/
       接着,我们在定义追求者类实现求爱行为接口,并且定义代理者类Proxy类同样实现求爱行为接口,并且该类要维护一个追求者类的引用,在各个重写方法中,通过该引用关联追求者类对象的相应方法。

**
 * 属于RealSubject类,该类的定义了一个追求者向梦中情人求爱的行动。
 */
class Persuitor implements LoveAction {
    
    private String name = null;
    
    public Persuitor(String name) {
        this.name = name;
    }// constructor

    @Override
    public void giveDolls(String girlName) {
        System.out.println(name + " give " + girlName + " Dolls!");
    }// giveDolls

    @Override
    public void giveFlower(String girlName) {
        System.out.println(name + " give " + girlName + " flower!");
    }// giveFlower

    @Override
    public void giveChocolate(String girlName) {
        System.out.println(name + " give " + girlName + " Chocolate!");
    }// giveChocolate
    
}/*Persuitor*/

/**
 * Proxy就为代理类,拥有与RealSubject完全一样的共有方法,内部有一个对RealSubject类引用的私有
 * 成员,在重写的方法中利用该成员实现对RealSubject类中相关方法的引用。
 */
class Proxy implements LoveAction {
    
    private Persuitor persuitor = null;
    
    public Proxy(Persuitor persuitor) {
        this.persuitor = persuitor;
    }// constructor
    
    @Override
    public void giveDolls(String girlName) {
        persuitor.giveDolls(girlName);
    }// giveDolls

    @Override
    public void giveFlower(String girlName) {
        persuitor.giveFlower(girlName);
    }// giveFlower

    @Override
    public void giveChocolate(String girlName) {
        persuitor.giveChocolate(girlName);
    }// giveChocolate
    
}/*Proxy*/

       最后是客户端代码,在客户端中并没有直接调用追求者的各种求爱行为方法,而是通过代理,也就是Tom的两个朋友实现了Tom给两位女孩送东西的目的。

public class ProxytDemo {
    
    /**
     * 客户端代码,注意用户并没有直接操作Persuitor类,所有的操作均由Agent类对象实现。
     * @param args
     */
    public static void main(String[] args) {
        Persuitor badBoy = new Persuitor("Tom");
        
        // 通过朋友1向Lily求爱
        System.out.println("In school 1: ");
        Proxy friend1 = new Proxy(badBoy);
        friend1.giveDolls("Lily");
        friend1.giveFlower("Lily");
        friend1.giveChocolate("Lily");
        
        // 通过朋友2向Lucy求爱
        System.out.println("In school 2: ");
        Proxy friend2 = new Proxy(badBoy);
        friend2.giveDolls("Lucy");
        friend2.giveFlower("Lucy");
        friend2.giveChocolate("Lucy");
    }// main
    
}/*ProxytDemo*/

执行结果:



三、完整代码

package dp5_proxy_pattern;

/**
 *  代理模式为其他对象提供一种代理以控制对这个对象的访问,它在客户与RealSubject之间设置了一个代
 *  理类,客户通过代理类访问RealSubject对象,因此代理类中有余客户类完全相同的方法,为了完全一致
 *  地实现客户类的功能,代理类中还要有一个客户类引用类型的私有成员。
 */
public class ProxytDemo {
    
    /**
     * 客户端代码,注意用户并没有直接操作Persuitor类,所有的操作均由Agent类对象实现。
     * @param args
     */
    public static void main(String[] args) {
        Persuitor badBoy = new Persuitor("Tom");
        
        // 通过朋友1向Lily求爱
        System.out.println("In school 1: ");
        Proxy friend1 = new Proxy(badBoy);
        friend1.giveDolls("Lily");
        friend1.giveFlower("Lily");
        friend1.giveChocolate("Lily");
        
        // 通过朋友2向Lucy求爱
        System.out.println("In school 2: ");
        Proxy friend2 = new Proxy(badBoy);
        friend2.giveDolls("Lucy");
        friend2.giveFlower("Lucy");
        friend2.giveChocolate("Lucy");
    }// main
    
}/*ProxytDemo*/

/**
 * 该类为Subject类, Subject类是从RealSubject和代理类中抽象出来的,从而可以在任何使用
 * RealSubject类的地方使用Proxy类。
 */
interface LoveAction {
    
    public void giveDolls(String girlName);
    public void giveFlower(String girlName);
    public void giveChocolate(String girlName);
    
}/*LoveAction*/

/**
 * 属于RealSubject类,该类的定义了一个追求者向梦中情人求爱的行动。
 */
class Persuitor implements LoveAction {
    
    private String name = null;
    
    public Persuitor(String name) {
        this.name = name;
    }// constructor

    @Override
    public void giveDolls(String girlName) {
        System.out.println(name + " give " + girlName + " Dolls!");
    }// giveDolls

    @Override
    public void giveFlower(String girlName) {
        System.out.println(name + " give " + girlName + " flower!");
    }// giveFlower

    @Override
    public void giveChocolate(String girlName) {
        System.out.println(name + " give " + girlName + " Chocolate!");
    }// giveChocolate
    
}/*Persuitor*/

/**
 * Proxy就为代理类,拥有与RealSubject完全一样的共有方法,内部有一个对RealSubject类引用的私有
 * 成员,在重写的方法中利用该成员实现对RealSubject类中相关方法的引用。
 */
class Proxy implements LoveAction {
    
    private Persuitor persuitor = null;
    
    public Proxy(Persuitor persuitor) {
        this.persuitor = persuitor;
    }// constructor
    
    @Override
    public void giveDolls(String girlName) {
        persuitor.giveDolls(girlName);
    }// giveDolls

    @Override
    public void giveFlower(String girlName) {
        persuitor.giveFlower(girlName);
    }// giveFlower

    @Override
    public void giveChocolate(String girlName) {
        persuitor.giveChocolate(girlName);
    }// giveChocolate
    
}/*Proxy*/


猜你喜欢

转载自blog.csdn.net/u013916933/article/details/51583774
今日推荐