Java设计模式——代理模式

前言:

上一篇说到了策略模式。单类图上来说,它和本篇要说的代理模式还真是有些像似。都需要一个公共的接口,还有一些实现类。代理类(包装类)封装了一个接口对象,提供客户端调用。这些都很类似。不过,有一个细节需要我们注意一下,那就是这里的代理类也需要去继承这里的公共接口。而在策略模式中,包装类则不需要这么做。

概述:

代理模式就是定义一个原对象的代理对象,来帮助原对象和系统之外的业务作沟通。也就是说,如果我们不能直接或是不愿直接去使用原对象,那么我们就可以使用创建一个原对象的代理来进行操作。

本文链接:http://blog.csdn.net/lemon_tree12138/article/details/50326817
-- Coding-Naga

--转载请注明出处

模式说明:

举例--话题访问

1.背景

现在我们假设我们要构建一个网站。这个网站允许三类用户访问,分别是:普通注册成员、站长管理员、游客。

那么这个时候,各个不同的访问者对某一网页的内容都有不同的权限。比如,普通注册成员可以访问、发表和评论(回复)一个话题;站长管理员可以访问、发表、评论以及删除一个话题;而游客则只能访问这个网页。

2.类图

图-1 代理模式类图

根据上面例子中的需求,我们可以画出图-1中的类图。不过虽然类图中的三个实现类都有实现接口中所有方法,不过其实这些实现方法却不适合所有的访问者对象。比如,Member虽然有remove方法,不过普通会员并不能真的删除一个话题。所以这个控制就十分有必要了。

3.代码及说明:

1.公共接口

在公共接口中需要定义一些访问者的基本行为。分别是访问话题、发表话题、评论话题和删除话题。

public interface Visitor {

    public void visit() throws RoleExcption;

    public void publish() throws RoleExcption;

    public void comment() throws RoleExcption;

    public void remove() throws RoleExcption;
}

2.具体实现类

本例中具体实现类倒没什么太多的内容,只是重写了实现接口中的方法。

public class Manager implements Visitor {

    @Override
    public void visit() {
        System.out.println("我是网站的管理员,我访问了这个主题");
    }

    @Override
    public void publish() {
        System.out.println("我是网站的管理员,我发表了一个主题");
    }

    @Override
    public void comment() {
        System.out.println("我是网站的管理员,我评论了一个主题");
    }

    @Override
    public void remove() {
        System.out.println("我是网站的管理员,我删除了一个主题");
    }
}

3.代理类

代理类的作用还是比较重要,和必要的。他们负责来控制一个访问者对话题的行为,防止越权的行为。比如一个游客访问者是不能发表和评论话题的。那么可以通过代理中方法作控制方式来实现。如下:

public class ProxyVisitor implements Visitor {

    private Visitor visitor = null;

    public ProxyVisitor() {
        // 默认情况是游客
        visitor = new Tourist();
    }

    public ProxyVisitor(Visitor _visitor) {
        visitor = _visitor;
    }

    @Override
    public void visit() throws RoleExcption {
        visitor.visit();
    }

    @Override
    public void publish() throws RoleExcption {
        if (visitor instanceof Tourist) {
            throw new RoleExcption("游客不能发表主题,请先注册帐号");
        }

        visitor.publish();
    }

    @Override
    public void comment() throws RoleExcption {
        if (visitor instanceof Tourist) {
            throw new RoleExcption("游客不能发表评论,请先注册帐号");
        }

        visitor.comment();
    }

    @Override
    public void remove() throws RoleExcption {
        if (!(visitor instanceof Manager)) {
            throw new RoleExcption("只有管理员才可以删除主题");
        }

        visitor.remove();
    }
}

4.客户端

这里我们通过不同的访问者进行不同的操作,观察结果。

public class VisitorClient {

    public static void main(String[] args) {
        Manager manager = new Manager();
        Member member = new Member();
        Tourist tourist = new Tourist();

        ProxyVisitor visitor = null;
        System.out.println("------------------- 1 --------------------");
        try {
            visitor = new ProxyVisitor(manager);
            visitor.visit();
            visitor.publish();
            visitor.comment();
            visitor.remove();
        } catch (RoleExcption e) {
            System.err.println(e);
        }
        ThreadUtils.sleep(50);

        System.out.println("------------------- 2 --------------------");
        try {
            visitor = new ProxyVisitor(member);
            visitor.visit();
            visitor.publish();
            visitor.comment();
            visitor.remove();
        } catch (RoleExcption e) {
            System.err.println(e);
        }
        ThreadUtils.sleep(50);

        System.out.println("------------------- 3 --------------------");
        try {
            visitor = new ProxyVisitor(tourist);
            visitor.visit();
            visitor.publish();
            visitor.comment();
            visitor.remove();
        } catch (RoleExcption e) {
            System.err.println(e);
        }
    }
}

5.测试结果

图-2 网站访问代理测试结果

举例--学生考试

1.背景

我们都经历过学生时代,也都有考过试,当然也都有作过弊(什么?你没有作过弊?那当我没说...)。

学生考试是一个公开的行为,而学生作弊却不能公开。所以,我们的考试方法是公有的,而作弊却是私有的。可是,如果我们的客户端程序需要我们在考试的时候来作一下弊。要怎么办呢?你可能会说,这好办,反射啊。的确是这样的,是要用到反射。不过这个反射我们封装在了代理类里面了,再从代理类里把这个方法打成公开的方法。在下面的类图中也会体现。

2.类图

这个类图跟上面话题访问者的类图很像。不过还是有一个地方不一样,发现了没有?那就是实现类中有一个比接口类中多出的方法cheat(作弊),且是一个私有的方法,不过在代理类里,这个方法被打成了公开的了。

图-3 代理模式类图

3.代码及说明

1.公共接口

说明同上

public interface Student {

    public void examinate();

    public void announce();

}

2.具体实现类

说明同上

public class SeniorStudent implements Student {

    private String name = "";
    private int score = 0;

    public SeniorStudent(String _name) {
        name = _name;
    }

    @Override
    public void examinate() {
        score = NumberUtils.randomInteger(40, 150);
    }

    @SuppressWarnings("unused")
    private void cheat() {
        System.out.println(name + "正在作弊...嘘...");
        score += (NumberUtils.randomInteger(150 - score));
    }

    @Override
    public void announce() {
        System.out.println(name + "考了" + score + "分");
    }

}

3.代理类

注意看这里的cheat方法,是一个公开的方法。在这个方法里,使用了Java的反射来实现对具体实现类的私有方法进行访问。

public class StudentProxy implements Student {

    private Student student = null;

    public StudentProxy(Student _student) {
        student = _student;
    }

    @Override
    public void examinate() {
        student.examinate();
    }

    @Override
    public void announce() {
        student.announce();
    }

    public void cheat() throws ClassNotFoundException, NoSuchMethodException,
            SecurityException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        Class<?> clazz = Class.forName(student.getClass().getName());
        Method method = clazz.getDeclaredMethod("cheat");
        method.setAccessible(true);
        method.invoke(student);
    }
}

4.客户端

说明同上

public class StudentProxyClient {

    public static void main(String[] args) {
        StudentProxy proxy = new StudentProxy(new Pupil("小明"));
        proxy.examinate();
        proxy.announce();

        try {
            proxy.cheat();
        } catch (ClassNotFoundException | NoSuchMethodException
                | SecurityException | IllegalAccessException
                | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }

        proxy.announce();
    }
}

5.测试结果

图-4 学生考试代理测试结果

GitHub源码下载:

https://github.com/William-Hai/DesignPattern-Proxy

时间: 2024-08-02 10:55:30

Java设计模式——代理模式的相关文章

一起学java设计模式--代理模式(结构型模式)

代理模式 应用软件所提供的桌面快捷方式是快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示(Picture),通过调用快捷方式的run()方法将调用应用软件(Application)的run()方法.使用代理模式模拟该过程,绘制类图并编程实现. package ProxyPattern; interface Software { void run(); } class Application implements Software { public void run() { Syste

Java设计模式-代理模式之动态代理(附源码分析)

Java设计模式-代理模式之动态代理(附源码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象.上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个.还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实习该方法,不符合设计模式原则. 动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类.每个代理类的对象都会关联一个表示内部处理

Java设计模式-代理模式之动态代理(附源代码分析)

Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代理是在编译的时候就确定了代理类详细类型.假设有多个类须要代理.那么就得创建多个. 另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法. 动态代理的做法:在执行时刻.能够动态创建出一个实现了多个接口的代理类.每一个代理类的对象都会关联一个表示内部处理逻辑的Inv

Java设计模式-代理模式之静态代理

Java设计模式-代理模式之静态代理 概念 为另一个对象提供一个替身或占位符以提供对这个对象的访问,使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理对象可以是远程的对象.创建开销大的对象或需要安全控制的对象 远程代理控制访问远程对象 虚拟代理控制访问创建开销大的资源 保护代理基于权限控制对资源的访问 看如下的类图: 仔细看上面的类图,首先是Subject它为RealSubject和Proxy提供了接口,通过实现同一个接口,Proxy在RealSubject出现的地方取代它,这点和适配

Java设计模式の代理模式

目录  代理模式 1.1.静态代理   1.2.动态代理 1.3.Cglib代理 代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法 举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的

Java设计模式—代理模式

代理模式(Proxy Pattern)也叫做委托模式,是一个使用率非常高的模式. 定义如下:     为其他对象提供一种代理以控制对这个对象的访问. 个人理解:        代理模式将原类进行封装,客户端不能直接找到原类,必须通过代理角色.即代理是原类的一个替身,客户端要找原类,统统找代理就可以搞定.明星和经纪人就是一种代理模式. 通用类图如下: 角色定义: ● Subject 抽象主题角色     抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求. ● Real S

java设计模式--代理模式

代理模式 proxy:为其他对象提供一种代理,并以控制对这个对象的访问,好比经纪人和明星之间的关系,经纪人就是明星的代理类.简单的就是在方法调用前后做处理,AOP思想,好处就是不改变原来类方法的基础上,动态的添加其他方法. 代理模式的3个角色 1.抽象角色2.真实角色 3.代理角色 1.静态代理 代理类调用被代理类的方法. 2.动态代理---比较常用 public interface People { void eat(); } public class Zhangsan implements

java 设计模式 - 代理模式 - 静态代理

代理模式:使用环境无法直接使用对象A(委托对象),可以使用对象B(代理对象)调用对象A已达到直接调用对象A的效果,就成为代理模式. 其中A为委托对象,B为代理对象. 静态代理的优缺点: 优点: 1.代码只管,可以清楚理解委托雷以及代理类. 2.在编译期加入,提前就指定好了委托类,代理类,效率高. 缺点: 1.静态代理很麻烦,需要大量的代理类,不易于代码维护等 当我们有多个目标对象需要代理时,我就需要建立多个代理类,改变原有的代码,改的多了就很有可能出问题,必须要重新测试. 2.重复的代码会出现在

23种设计模式----------代理模式(三) 之 动态代理模式

(上一篇)种设计模式----------代理模式(二) 当然代理模式中,用的最广泛的,用的最多的是  动态代理模式. 动态代理:就是实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理. 抽象接口的类图如下: --图来自设计模式之禅 所以动态代理模式要有一个InvocationHandler接口 和 GamePlayerIH实现类.其中 InvocationHandler是JD提供的动态代理接口,对被代理类的方法进行代理. 代码实现如下 抽象主题类或者接口: 1 package com.ye