zoukankan      html  css  js  c++  java
  • Java设计模式——代理模式

    前言

      上一篇说到了策略模式。

    单类图上来说,它和本篇要说的代理模式还真是有些像似。

    都须要一个公共的接口,另一些实现类。代理类(包装类)封装了一个接口对象,提供client调用。这些都非常相似。只是。有一个细节须要我们注意一下,那就是这里的代理类也须要去继承这里的公共接口。而在策略模式中。包装类则不须要这么做。

    概述

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


    版权说明

    著作权归作者全部。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    作者: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.client

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

    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.背景

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

      学生考试是一个公开的行为。而学生作弊却不能公开。所以。我们的考试方法是公有的。而作弊却是私有的。

    但是,假设我们的client程序须要我们在考试的时候来作一下弊。

    要怎么办呢?你可能会说。这好办。反射啊。的确是这种。是要用到反射。只是这个反射我们封装在了代理类里面了,再从代理类里把这种方法打成公开的方法。在以下的类图中也会体现。

    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.client

    说明同上

    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

  • 相关阅读:
    POJ3294Life Forms(广义后缀自动机)(后缀数组+二分+数状数组)
    URAL1517Freedom of Choice(后缀数组)
    POJ2406Power Strings (最小循环节)(KMP||后缀数组)
    POJ2774Long Long Message (后缀数组&后缀自动机)
    SPOJ705 Distinct Substrings (后缀自动机&后缀数组)
    Nacos: Namespace 和 Endpoint 在生产环境下的最佳实践
    阿里PB级Kubernetes日志平台建设实践
    深度解读Helm 3: 犹抱琵琶半遮面
    开发者说:如何参与定义一款 IDE 插件
    从开源小白到 Apache Member,我的成长之路
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7025738.html
Copyright © 2011-2022 走看看