歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java 代理模式應用

代理模式是一種效率非常高的模式,其定義如下:提供一種代理以控制對這個對象的訪問。

代理模式也叫委托模式,它是一項基本設計技巧。許多其他的設計模式,如狀態模式,策略模式,訪問者模式本質上是在更特殊的場合上采用了委托模式,代理模式在日常的使用中能夠提供更好的訪問控制。

1: 抽象角色

抽象主題角色類可以是一個接口,是一個普通的業務類型定義,無特殊要求。


2:具體角色

也叫被委托角色,這個角色才是真正干活的角色,是業務邏輯的具體執行者


3:代理主題角色


也叫做委托類,代理類,它負責對真實角色的應用,把所有抽象主題類定義的方法限制委托給真實角色實現,並且在真實主題角色

處理完畢前後做預處理和善後工作。

--------------------------------------分割線 --------------------------------------

編寫高質量代碼 改善Java程序的151個建議 PDF高清完整版 http://www.linuxidc.com/Linux/2014-06/103388.htm

Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm

Java對象初始化順序的簡單驗證 http://www.linuxidc.com/Linux/2014-02/96220.htm

Java對象值傳遞和對象傳遞的總結 http://www.linuxidc.com/Linux/2012-12/76692.htm

Java對象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm

--------------------------------------分割線 --------------------------------------

定義一個接口:

 package com.zzu.proxy;

public interface Movable {
    void run();
}

實現類

package com.zzu.proxy;

public class Tank implements Movable{

 @Override
 public void run() {
       
        try {
         System.out.println("Tank is running.....");
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }

}

代理類

package com.zzu.proxy;

public class TankLogProxy implements Movable{

 public TankLogProxy(Movable t) {
  super();
  this.t = t;
 }
 Movable t;

 @Override
 public void run() {
  System.out.println("start log...");
          t.run();   
        System.out.println("end log....");
 }
   
}

另外一個代理類

package com.zzu.proxy;

public class TankTimeProxy implements Movable{

 public TankTimeProxy(Movable t) {
  super();
  this.t = t;
 }
 Movable t;

 @Override
 public void run() {
  System.out.println("time start...");
  long start = System.currentTimeMillis();
          t.run();   
        long end = System.currentTimeMillis();
        System.out.println("time: "+(end - start));
 }
   
}

client類

package com.zzu.proxy;

public class Client {
    public static void main(String[] args) {
  Movable m = new Tank();
  TankLogProxy tlp =  new TankLogProxy(m);
  TankTimeProxy ttp = new TankTimeProxy(tlp);
  Movable b = ttp;
  b.run();
 }
}

其實代理真正有意思的地方還是在於動態代理。下面說說動態代理的內在原理

 

動態代理:它和普通代理的不同地方在於,他在實現階段不用關心代理誰,而是在運行階段來指定哪一個對象。

它的實現實際上是通過JDK提供的 InvocationHandler,下面我們通過代碼的形式來研究一下動態代理的內在執行機制

我們先定義一個接口:

package dynamic;

public interface Subject {
 // 業務操作
 public void doSomething(String str);
 //增加一個方法
 public void doGirl();
}

接口的實現

package dynamic;

public class RealSubject implements Subject {

 @Override
 public void doSomething(String str) {
  System.out.println("do some things -->>> " + str);
 }

 @Override
 public void doGirl() {
        System.out.println("to find a girl --->>>>> "); 
 }

}

動態代理的handler類

package dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 其中的InvocationHandler是JDK提供的動態代理的接口,其中的invoke方法是InvocationHandler必須實現的,它完成對真實方法的調用,即所有的真實方法調用都交給handler來接管
 * @author Administrator
 *
 */
public class MyInvocationHandler implements InvocationHandler {
 // 被代理的對象
 private Object target = null;

 // 通過構造函數傳遞一個對象

 public MyInvocationHandler(Object _obj) {
  this.target = _obj;
 }

 @Override
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  return method.invoke(this.target, args);
 }

}

動態代理類

package dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class DynamicProxy<T> {
 public static <T> T newProxyInstance(ClassLoader loader,
   Class<?>[] interfaces, InvocationHandler h) {
  // 尋找joinPoint連接點,AOP框架使用元數據定義
  if (true) {
   // 執行前一個通知
   new BeforeAdvice().exec();
  }
  return (T) Proxy.newProxyInstance(loader, interfaces, h);

 }
}

動態代理的場景類

package dynamic;

import java.lang.reflect.InvocationHandler;

public class Client {

 /**
  * @param args
  */
 public static void main(String[] args) {
        //定義一個主題
  Subject subject = new RealSubject();
  //定義一個handler
  InvocationHandler handler = new MyInvocationHandler(subject);
  //定義主題的代理
  Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
  //代理的行為,
  proxy.doSomething("Finish");
  proxy.doGirl();
 }

}

動態代理實際上個人感覺和普通代理沒什麼區別,實際上的作用就是在不改變代碼的情況下增強或控制對象的行為,
 
動態代理實現代理的職責,業務邏輯實現相關的邏輯功能,兩者之間沒有必然的相互耦合的關系。

Copyright © Linux教程網 All Rights Reserved