• 1代理模式


    代理模式

    代理模式(Proxy Pattern)也叫委托模式,是一个使用率非常高的模式。

    1代理模式的定义
    代理模式的英文原话是:
    Provide a surrogate or placeHolder for another object to control access to it.
    意思是:为其他对象提供一种代理以控制对这个对象的访问。

    代理模式是一项基本的设计技巧,许多其他模式,如状态模式策略模式访问者模式本质上也采用了代理模式
    代理模式提供一下3个角色。
    • 抽象主题(Subject)角色:该角色是真实主体和代理主体的共同接口,以便在任何可以使用真实主体的地方都可以使用代理主体。
    • 代理主体(Proxy Subject)角色:也叫作委托类、代理类,该角色负责控制对真实主体的引用,负责在需要的时候创建或删除真实主题对象,并且在真实主题角色处理完毕前后座预处理和善后处理工作。
    • 真实主题(Real Subject)角色:也叫被委托角色、被代理角色,是业务逻辑具体执行者。

    一些比较易于理解的例子:
    1.Windows里的快捷方式。
    2.猪八戒找高翠兰,结果是孙悟空变的。可以理解为,把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,猪八戒访问高翠兰时看不出来高翠兰这个代理类。
    3.买火车票不一定在火车站买,也可以去代售点。
    4.一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。
    5.spring中的aop。

    代理模式的类图

    创建抽象主题
    Subject.java
    package com.eric.结构型模式.代理模式.引例;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 抽象主题类
     * @CreateTime 2020-11-28 08:32:13
     */
    public interface Subject {
        //定义一个请求方法
        public void request();
    }
    创建真实主题
    RealSubject.java
    package com.eric.结构型模式.代理模式.引例;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 真实主题
     * @CreateTime 2020-11-28 08:33:10
     */
    public class RealSubject implements Subject{
        @Override
        public void request() {
            //业务处理
            System.out.println("我处理了一个业务...");
        }
    }
    创建代理类
    ProxySubject.java
    package com.eric.结构型模式.代理模式.引例;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 代理主题
     * @CreateTime 2020-11-28 08:34:31
     */
    public class ProxySubject implements Subject {
        private Subject subject;
        public ProxySubject(Subject subject){
            this.subject = subject;
        }
        //实现请求方法
        @Override
        public void request() {
            this.beforeRequest();
            subject.request();
            this.afterRequest();
        }
    
        //请求前操作
        private void beforeRequest()
        {
            //预处理
            System.out.println("代理类的预处理...");
        }
        //请求后的操作
        private void afterRequest()
        {
            System.out.println("代理类的善后处理...");
        }
    }

    注意事项:
    • 与适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
    • 与装饰者模式的区别:装饰者模式是为了增强功能,代理模式则是为了加以控制。

    2代理模式的应用
        a.代理模式的种类
      • 远程(Remote)代理:为一个位于不同空间的对象提供一个局部代表对象。这个不同地址空间,可以使本机也可以在另一台机器中。  
      • 虚拟(Virtual)代理:有时需要创建一些消耗较多资源的对象,可以首先创建代理对象,而将真实对象的创建延迟。例如,加载一个很大的图片,可以通过图片的代理来代替真正的图片。
      • 保护(Protect Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。
      • 缓存(Cache)代理:为一个目标操作的结果提供链式的存储空间,以便多个客户端可以共享这些结果。
      • 同步(Sychronization)代理:使几个用户能够同时使用一个对象而没有冲突。
      • 智能(Smart Reference)引用:当一个对象被引用时,提供一些额外的操作,例如,记录访问的流量和次数等。
    注意: 在所有种类的代理中,虚拟代理远程代理智能代理保护代理是最为常见的代理模式。  

        b.代理模式的优点
      • 职责清晰:真实角色实现实际的业务逻辑,不用关心其他非本职的事物,通过后期的代理完成附加的事物,附带的结果就是编程简洁清晰。
      • 高扩展性:具体主体角色随需求不同可能有很多种,但只要实现了接口,代理类就完全可以在不作任何修改的情况下代理各种真实主题角色。
      • 智能化:代理类可以在运行时才确定需要去代理的真实主题,这是一种强大的功能。
        c.代理模式的使用场景
    运用很广泛,大到系统框架、企业平台,小到事务处理、代码片段,随处可见代理模式的使用。例如,java RMI的远程调用就是一种代理模式的应用,现在流行的AOP也可以通过代理模式实现。
    3代理模式实例
    例1:游戏代练
    IGamePlayer接口对游戏玩家进行抽象
    IGamePlayer.java
    package com.eric.结构型模式.代理模式.例1;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 游戏接口
     * @CreateTime 2020-11-29 18:01:15
     */
    public interface IGamePlayer {
        public void killBoss();//杀Boss
        public void upGrade();//升级
    }
    GamePlayer实现IGamePlayer接口,是玩家
    GamePlayer.java
    package com.eric.结构型模式.代理模式.例1;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 玩家类
     * @CreateTime 2020-11-29 18:02:38
     */
    public class GamePlayer implements IGamePlayer{
        private String name= "";
        public GamePlayer(String name){
            this.name = name;
        }
    
        public void killBoss(){
            System.out.println(this.name+"杀Boss中...");
        }
        public void upGrade(){
            System.out.println("成功升了一级!!!");
        }
    }
    代理类则实现IGamePlayer接口,并实现两个私有方法日志和消耗时间方法。
    GamePlayerProxy.java
    package com.eric.结构型模式.代理模式.例1;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 游戏代练
     * @CreateTime 2020-11-29 18:05:44
     */
    public class GamePlayerProxy implements IGamePlayer {
        private IGamePlayer player = null;
        public GamePlayerProxy(IGamePlayer player){
            this.player = player;
        }
        //记录打怪时间
        private void log(){
            String pattern = "YYYY-MM-dd HH:mm:ss";
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    
            System.out.println("打怪时间: "+sdf.format(new Date()));
        }
    
        @Override
        public void killBoss() {
            this.log();
            player.killBoss();
        }
    
        @Override
        public void upGrade() {
            player.upGrade();
            this.count();
        }
        //计算升级所用时间
        private void count()
        {
            System.out.println("升1级耗费100小时!");
        }
    }
    测试
    ClientDemo.java
    package com.eric.结构型模式.代理模式.例1;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 测试类
     * @CreateTime 2020-11-29 18:35:46
     */
    public class ClientDemo {
        public static void main(String[] args) {
            IGamePlayer player = new GamePlayer("Eric");
            GamePlayerProxy proxy = new GamePlayerProxy(player);
    
            proxy.killBoss();
            proxy.upGrade();
        }
    }
    测试结果:

    例2:图片的代理
    我们将创建一个Image接口和实现了Image接口的实体类。ImageProxy是一个代理类,减少RealImage对象加载的内存占用。
    ProxyPatternDemo类使用ProxyImage来获取要加载的Image对象,并按照需求进行显示。

    步骤1
    创建接口
    Image.java
    package com.eric.结构型模式.代理模式.例2;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 图片接口
     * @CreateTime 2020-11-29 19:03:44
     */
    public interface Image {
        void display();
    }

    步骤2
    创建接口的实现类
    RealImage.java
    package com.eric.结构型模式.代理模式.例2;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 真实的图片
     * @CreateTime 2020-11-29 19:04:48
     */
    public class RealImage implements Image {
        private String fileName;
    
        public RealImage(String fileName){
            this.fileName = fileName;
            loadFromDisk(fileName);
        }
    
        @Override
        public void display() {
            System.out.println("正在显示..."+fileName);
        }
    
        private void loadFromDisk(String fileName){
            System.out.println("从硬盘加载中..."+fileName);
        }
    }
    ImageProxy.java
    package com.eric.结构型模式.代理模式.例2;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 图片代理类
     * @CreateTime 2020-11-29 19:25:24
     */
    public class ImageProxy implements  Image {
        private RealImage realImage;
        private String fileName;
    
        public ImageProxy(String fileName){
            this.fileName = fileName;
        }
    
        @Override
        public void display() {
            if(realImage == null)
                realImage = new RealImage(fileName);
            realImage.display();
        }
    
    }
    步骤三
    测试
    package com.eric.结构型模式.代理模式.例2;
    
    /**
     * @author Eric
     * @ProjectName my_design_23
     * @description 测试类
     * @CreateTime 2020-11-29 19:28:26
     */
    public class ProxyPatternDemo {
        public static void main(String[] args) {
            Image image = new ImageProxy("test01.jpg");
            //图片从硬盘加载
            image.display();
            System.out.println("--------------------");
            //图片不需要从硬盘加载
            image.display();
        }
    }
    测试结果
    可以看出第一次从硬盘中加载了图片,而第二次则是从缓存中加载图片。





    只要你不停下来,慢一点也没关系。
  • 相关阅读:
    gym 101480 Problem C: Cow Confinement 题解
    Uva 1072 Huffman Codes 题解
    NERC 2015 Hypercube 题解
    ACM ICPC 2017 WF Problem J Son of Pipe Stream题解
    CF Round # 295 (Div. 1)题解
    CF 1444 D Rectangular Polyline 题解
    BZOJ3308 九月的咖啡店
    BZOJ4025 二分图
    BZOJ4000 [TJOI2015]棋盘
    BZOJ3999 [TJOI2015]旅游
  • 原文地址:https://www.cnblogs.com/zyl-0110/p/14113449.html
Copyright © 2020-2023  润新知