zoukankan      html  css  js  c++  java
  • [设计模式]代理模式

    1. 定义

      为其他对象提供一种代理以控制对这个对象的访问。

      代理模式是通过创建一个代理对象,用这个代理对象去代表真实的对象,客户端得到这个代理对象后,对客户端并没有什么影响,就跟得到了真实对象一样来使用。

        当客户端操作这个代理对象的时候,实际上功能最终还是会由真实的对象来完成,只不过是通过代理操作的,也就是客户端操作代理,代理操作真正的对象。

    2. 类图

      

      Proxy: 代理对象,通常包含了以下功能,实现了与具体目标对象一样的借口,保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象,可以控制对具体目标对象的访问,并可以负责创建和删除它。

      Subject: 目标对象,定义代理和具体目标对象的借口。

      RealSubject: 具体目标对象,真正实现目标对象要求的功能。

    3. 实例

      

    package com.jerry.designpattern.proxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午10:39:09
     */
    public interface Player {
        void killMonster();
    }
    
    package com.jerry.designpattern.proxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午10:46:10
     */
    public class PlayerImpl implements Player{
        
        /**
         * 经验值 experience points
         */
        private int exp;
        
        /**
         * 等级
         */
        private int level;
        
        public PlayerImpl() {
            level = 1;
        }
        
        @Override
        public void killMonster() {
            // TODO Auto-generated method stub
            System.out.println("杀死一个怪物,获得50点经验");
            exp += 50;
            upgrade();
        }
        
        /**
         * 升级
         */
        private void upgrade() {
            // TODO Auto-generated method stub
            if (exp % 100 == 0) {
                this.level++;
                System.out.println("恭喜你升级了,当前等级为: " + this.level);
            }
        }
    
    }
    
    package com.jerry.designpattern.proxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午11:05:01
     */
    public class GameProxy implements Player{
        
        private Player player;
        
        public GameProxy(Player player) {
            this.player = player;
        }
        
        @Override
        public void killMonster() {
            // TODO Auto-generated method stub
            System.out.println("游戏公式代理升级,一次升10级");
            for (int i = 0; i < 20; i++) {
                player.killMonster();
            }
        }
        
    }
    
    package com.jerry.designpattern.proxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午11:00:54
     */
    public class Client {
        public static void main(String[] args) {
            
            /*
             * 不使用游戏代理,自己手动杀怪升级
             */
            Player player1 = new PlayerImpl();
            player1.killMonster();
            player1.killMonster();
            player1.killMonster();
            player1.killMonster();
            
            /*
             * 花费money找代理升级
             * 一次升10级
             */
            Player player2 = new PlayerImpl();
            Player proxy = new GameProxy(player2);
            proxy.killMonster();
            proxy.killMonster();
        }
    }

    4. 代理的分类

     代理大致可以分为:

      虚代理:根据需要来创建开销很大的对象,该对象只有在真正使用的时候才被创建。  

      远程代理:用来在不同地址空间上代表相同的一个对象,这个不同地址空间可以在本机上,也可以在其他机器上。在Java中最经典的是RMI

      copy-on-write代理:在客户端操作的时候,只有对象确实改变了,才会真正的拷贝或克隆一个目标对象,算是虚代理的一个分支。

      保护代理:控制原始对象的访问,如果有需要,可以给不同的用户提供不同的访问权限,以控制对原始对象的访问。

      Cache代理:为那些昂贵操作的结构提供临时空间,以便多个客户端可以共享这些结果。

        防火墙代理:保护对象不被恶意用户访问和操作。

        同步代理:使多个用户能够同时访问目标对象而没有冲突。

        智能指引:在访问对象时执行一些附加的操作。

    5. 动态代理

      Java对代理模式提供了内建的支持,在java.lang.reflect包下面,提供了一个Proxy和一个InvacationHandler接口,通常前面自己实现的代理模式称为静态代理,使用Java提供的功能实现的代理模式称为动态代理,

      

    package com.jerry.designpattern.dynamicproxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午10:39:09
     */
    public interface Player {
        void killMonster();
    }
    
    package com.jerry.designpattern.dynamicproxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午10:46:10
     */
    public class PlayerImpl implements Player{
        
        /**
         * 经验值 experience points
         */
        private int exp;
        
        /**
         * 等级
         */
        private int level;
        
        public PlayerImpl() {
            level = 1;
        }
        
        @Override
        public void killMonster() {
            // TODO Auto-generated method stub
            System.out.println("杀死一个怪物,获得50点经验");
            exp += 50;
            upgrade();
        }
        
        /**
         * 升级
         */
        private void upgrade() {
            // TODO Auto-generated method stub
            if (exp % 100 == 0) {
                this.level++;
                System.out.println("恭喜你升级了,当前等级为: " + this.level);
            }
        }
    
    }
    
    package com.jerry.designpattern.dynamicproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午11:13:19
     */
    public class GameProxy implements InvocationHandler{
        
        public Player player;
        
        public GameProxy(Player player) {
            this.player = player;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("使用游戏代理升级,一次升10级");
            for (int i = 0; i < 20; i++) {
                method.invoke(player, args);
            }
            return null;
        }
        
        public Player getInstance() {
            return (Player)Proxy.newProxyInstance(player.getClass().getClassLoader(), 
                    player.getClass().getInterfaces(), 
                    this);
        }
    
    }
    
    package com.jerry.designpattern.dynamicproxy;
    /**
     * 
     * @author Jerry
     * @date 2015年1月21日 上午11:20:16
     */
    public class Client {
        public static void main(String[] args) {
            Player player = new PlayerImpl();
            GameProxy gameProxy = new GameProxy(player);
            Player playerProxy = gameProxy.getInstance();
            playerProxy.killMonster();
        }
    }
  • 相关阅读:
    蓝奏云的链接打不开
    数据链路层
    markdown(md)
    物理层
    计算机网络概述
    86五笔学习笔记
    Ubuntu初次使用的问题
    Hello Word!
    快速创建Flask Restful API项目
    Ubuntu环境下部署Django+uwsgi+nginx总结
  • 原文地址:https://www.cnblogs.com/jerry19890622/p/4310007.html
Copyright © 2011-2022 走看看