问题的提出

现在生活中,常常在微信朋友圈里面看到代购的信息,你想在国外买什么,香港买什么,但是又懒得自己过去,于是常常委托别人帮忙买奶粉买那啥的。这类问题的缘由是因为客户和原产地没有直接的接触,所以需要一个代理(代购)的第三者来实现间接引用。代理对象可以在客户端和目标对象间起到中介作用,而且可以通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务。代理模式是一种很好实现客户对象与代理对象分离的策略。其抽象UML图如下图

Java设计模式:代理模式(一)

代理模式包含如下角色

ISubject:抽象主题角色,是一个接口。该接口是对象和它的代理公用的接口。

RealSubject:真实的主题角色,是实现主题接口的类。

Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

买电视为例

1)定义抽象主题-买电视

public interface ITV {
    public void buyTV();
}

2)定义实际主题-买电视过程

public class Buyer implements ITV {
    public void buyTV(){
        System.out.println("I have bought the TV by buyer proxy");
    }
}

3)定义代理

public class BuyerProxy implements ITV {
    private Buyer buyer;
    public BuyerProxy(Buyer buyer){
        this.buyer = buyer;
    }
    public void buyTV(){
        preProcess();
        buyer.buyTV();
        postProcess();
    }
    public void preProcess(){
        //询问客户需要的电视类型,价位等信息
    }
    public void postProcess(){
        //负责把电视送到客户家(售后服务)
    }
}

在这里,一开始看到这样的设计的时候。会有这样的疑问,代理和实际主题为什么都要实现相同的接口呢?而且接口方法的实现完全一样。当从代码段分析,确实感到很累赘。但是,结合实际想想,你需要代理者帮你买东西,那作为代理者,理所因当必须要有和你一样的功能:买东西!代理对象提供与真实对象相同的接口,以便在任何时刻都能替代真实对象。

代理模式最突出的特点:代理角色与实际主题角色有相同的父类接口。常用的代理方式有4类:虚拟代理,远程代理,计数代理,动态代理。

下面分别简单介绍一下这四种代理模式

 

一.虚拟代理

虚拟代理的关键思想是:如果需要创建的对象资源消耗较大,那就先创建一个消耗相对比较小的对象表示。真正完整的对象只有在需要时才会被创建。当用户请求一个“大”的对象时,虚拟代理在该对象真正被创建出来之前扮演着替身的角色;当对象被创建出来后,虚拟代理将用户请求直接委托给对象。

看下面这个例子,高校本科生科研信息查询功能设计

实验室数据库表字段说明

Java设计模式:代理模式(一)

可以看出,第4,5个字段都是大段的文字,如果直接列出申请所有项目信息,一方面会花费比较多时间,另一方面界面也难设计,因为前三个字段较短,后面较长。良好的查询策略应该分为二级查询,第一级查询显示“账号,姓名,项目名称”三个字段,第二级查询时当鼠标选中表中某一个具体项目时,再进行一次数据库查询,得到项目完整信息。

Mysql数据表简单设计

 

    create table project(
        account varchar(20),
        name varchar(20),
        project varchar(20),
        content varchar(20),
        plan varchar(20)
    )

View Code