Java设计模式——代理模式

来源:互联网 发布:打码软件破解 编辑:程序博客网 时间:2024/04/28 03:37

前言

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

概述

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


版权说明

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Coding-Naga
发表日期: 2015年12月19日
链接:http://blog.csdn.net/lemon_tree12138/article/details/50326817
来源:CSDN
更多内容:分类 >> 设计模式


模式说明

举例--话题访问

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

1 0
原创粉丝点击