【BigHereo 9】-----设计模式之动态代理

来源:互联网 发布:手机有网络不能看视频 编辑:程序博客网 时间:2024/06/09 17:15


 

【BigHereo 9】------设计模式之动态代理

 

 

【前言】

     所有的设计模式中,你知道实现起来那个最好给力吗?动态代理,当之无愧是所有设计模式中,等你用完之后是会有一种无比自豪感觉.今天小编就代理来领略一下什么是动态代理.

 

 

在了解动态代理之前,看看你能否回答下面几个问题:

   1,什么是代理?什么是代理模式

   2,什么是静态代理?什么是动态代理?

   3,代理模式有什么东西?

   4,代理模式有什么优缺点?

   5,代理模式能干什么? 怎么干?

   6,Proxy的应用场景和最佳实践?

   7,Proxy, Adapter(适配器),Decorator(装饰器)的对比?


 

【谋全局】

 

 

 

 

 下面我就用装饰模式的方法,一层一层的给您细细道来:


 

1,什么是代理,什么是代理模式?

     代理: 不是自己亲自做干某件事,找一个代理,但是事是同一件.例如,你想买盐,你叫你舍友给你带回来,这过程就是一个代理. 都是买盐,但不是你自己去买,而是你同事代你买的.

 

    代理模式: 什么是设计模式? 通俗的说,设计模式就是一种解决问题的思路,或方法. 代理模式就是用代理的方式来解决问题.



UML图:

          

 

 

简单的类图:

            



2,什么是静态代理?什么是动态代理?

   静态代理: 程序运行前就已经存在代理字节码,代理类和委托关系在运行前就已经确定了.

 

   动态代理: 运行前没有确定代理类和委托关系,运行接口才指定哪一个对象.

                     动态代理不需要实现接口,所以动态代理也叫: jdk代理.


 

3,代理模式有什么东西?

      通过上面的两个问题,我们可以总结出来,代理模式有两种: 静态代理和动态代理.


 

 

4,代理模式有什么优缺点?

            



 

5,代理模式能干什么? 怎么干?

   1,远程代理(Remote Proxy):

       物理位置不同

 

   2,虚拟(Virtual Proxy): 

      创建开销很大对象---例如图片加载,先加载一个图框; 算法很长先加载一部分.

 

   3,保护/安全(Protection Proxy): 

       控制原对象访问权限

 

   4,智能指引(Smart Reference)

        取代简单的指针,访问对象时执行一些附加操作.

 

  5,Copy-on-Write代理

       把复制(克隆)延迟到客户端真正需要是才执行.

 

 

6,Proxy的应用场景和最佳实践?

       




7,Proxy, Adapter(适配器),Decorator(装饰器)的对比?

     




【举个栗子】

 

 

 

 

 

共用接口: Moveable:

package proxy;/** * Created by Daniel on 2017/8/23. */public interface Moveable{    void move();    //继承方式实现代理,写很多的继承,非常的麻烦} 


真实类: Tank1:

package proxy;import java.util.Random;/** * Created by Daniel on 2017/8/23. */public class Tank1 implements Moveable{    //代理实现方式,继承和聚合两中方式    @Override    public void move() {        long start =System.currentTimeMillis();        System.out.println("Tank1 Moving,,,,,");        try {            Thread.sleep(new Random().nextInt(10000));        } catch (InterruptedException e) {            e.printStackTrace();        }        long end=System.currentTimeMillis();        //想知道一共多长时间?        System.out.println("time:"+ (start-end));        //代理:知道日志        //代理: 添加事务,让事务进行回滚    }}


 

代理类: Tank2Proxy:

package proxy;/** * Created by Daniel on 2017/8/23. */public class Tank2Proxy extends Tank1 {    //方法一: 继承实现    @Override    public  void  move(){        long start=System.currentTimeMillis();        super.move();        long end=System.currentTimeMillis();        System.out.println("time"+(end-start));    }} 


客户端: Client:

package proxy;/** * Created by Daniel on 2017/8/23. */public class Client {   public  static void  main(String[] args){       //继承方法实现记录       oveable m=new Tank2Proxy();       m.move();     }}

 

 

【代理中的继承和聚合】

   代理的实现有两种方式,继承和聚合,设计模式中一个非重要的原则就是: 多用集合少用继承.

 

   从我们这个代理模式也可以体现出来:

方法一: 继承实现代理:

package proxy;/** * Created by Daniel on 2017/8/23. */public class Tank2Proxy extends Tank1 {    //方法一: 继承实现    @Override    public  void  move(){        long start=System.currentTimeMillis();        super.move();        long end=System.currentTimeMillis();        System.out.println("time"+(end-start));    }}


 

方法二: 聚合实现

package proxy;/** * Created by Daniel on 2017/8/23. */public class TankTimeProxy implements  Moveable{    //方法二:聚合实现    public TankTimeProxy(Moveable t) {        super();        this.t = t;    }    Moveable t;    @Override    public void move()  {        long start=System.currentTimeMillis();        System.out.println("startTime:"+start);        t.move();        long end=System.currentTimeMillis();        System.out.println("endTime:"+end);        System.out.print("time:"+(end-start));    }}


  

客户端代码:

package proxy;/** * Created by Daniel on 2017/8/23. */public class Client {   public  static void  main(String[] args){       //继承方法实现记录       /*Moveable m=new Tank2Proxy();       m.move();*/       //================聚合方法实现===========================       /*Tank1 t=new Tank1();       //日志包着时间---先记录时间,再日志       TankTimeProxy ttp =new TankTimeProxy(t);       TankLogProxy tlp=new TankLogProxy(ttp);       Moveable m=tlp;       m.move();*/       Tank1 t=new Tank1();       //时间包着日志,先记录日志,才有时间       TankLogProxy tlp=new TankLogProxy(t);       TankTimeProxy ttp =new TankTimeProxy(tlp);       Moveable m=ttp;       m.move();     }}

 

 

【小结】

    1,从小到大,很有意思的一个大家都了解的例子就是:   猪八戒背媳妇,后来发现背上的高翠兰是孙悟空变得,这里孙悟空是代理类,主要是让高翠兰安全得到保护.

   

   2,为什么集合比继承好?

   (1)继承虽然简单,但相对于聚合来说,不安全,继承破坏封装的类.

      (2)用继承,基类改变了,派生类也会随之改变.

      (3)从基类继承而来的派生类是静态的,不可能在运行时间内发生改变,没有足够的灵活性.