《賽博朋克2077》新補丁正在測試 大型更新或將上線
文章目錄
設計模式目錄:https://blog.csdn.net/qq_52681418/article/details/114828850
設計模式-代理模式
代理模式代理一個類,不修改類而增加類的功能。
幾種代理模式的比較
- jdk靜態代理:需要類、代理器類必須繼承同一個介面。
- jdk動態代理:需要類、代理器類都必須繼承介面(不同一個)。
- cglib動態代理:代理器繼承介面。
1.靜態代理
你有一個類已經寫好了,不能修改了,你想擴充套件它該怎麼辦呢?
你在寫這個類的時候,讓它繼承一個介面,然後建立一個代理器,代理器管理這個類並新增更多的功能。
1.這是你寫好的類繼承的介面(或繼承抽象類)
public interface ParentInterFace {
void show();
}
2.這是你的類
public class Goods implements ParentInterFace {
public void show() {
System.out.println("這是一個不能修改的類");
}
}
3.建立一個代理器,代理器需要指定代理的目標,因此傳入,並且代理器實現目標類實現的介面
public class Poxy implements ParentInterFace {
protected ParentInterFace goods;
public Poxy(ParentInterFace goods) {
this.goods = goods;
}
//代理
public void show() {
System.out.println("---執行前擴充套件");
goods.show();
System.out.println("---執行後擴充套件");
}
}
啟動代理步驟
public class
Main { public static void main(String[] args) { ParentInterFace goods = new Goods(); //建立一個類 ParentInterFace goods2 = new Poxy(goods); //代理該類 goods2.show();//輸出結果 } }結果
代理模式和裝飾者模式很像,裝飾者模式類為代理器建立子類,由子類擴充套件
這樣做需要代理類、目標類都實現同一個介面或繼承同一個抽象類,但有時候我們不想讓它們繼承同一個介面,我們如何代理呢?
此時我們就需要jdk動態代理、cglib來實現
2.JDK動態代理
代理器實現 InvocationHandler 介面
1.你的介面:必須有介面,只不過代理器不用實現
public interface ParentInterFace {
void show();
}
1.一個普通類
public class Goods implements ParentInterFace{
public void show() {
System.out.println("這是一個類");
}
}
2.代理器:實現InvocationHandler 介面,並實現invoke方法,在此方法中進行代理
public class Poxy implements InvocationHandler {
protected ParentInterFace goods;
//傳入目標類
public Poxy(ParentInterFace goods) {
this.goods = goods;
}
//繼承的呼叫器(實現代理)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("---執行前擴充套件");
Object invoke=method.invoke(goods,args);
System.out.println("---執行後擴充套件");
return invoke;
}
}
invoke實際上通過反射調取物件的方法。
開始代理
public class Main { public static void main(String[] args) { ParentInterFace goods=new Goods(); //建立一個類 InvocationHandler poxy=new Poxy(goods); //代理 ClassLoader classLoader=poxy.getClass().getClassLoader();//獲取代理類的類載入器 Class<?>[] classes=goods.getClass().getInterfaces(); //獲取目標類實現的介面 ParentInterFace goods2= (ParentInterFace) Proxy.newProxyInstance(classLoader,classes,poxy);//建立jdk代理物件 goods2.show(); } }
結果
3.CGlib動態代理
可在執行期擴充套件java類和實現java介面,底層通過使用位元組碼處理框架ASM,來轉換位元組碼並生成新的類。
- spring的AOP就是使用cglib動態代理實現的。
- Hibernate用它來實現PO(Persistent Object 持久化物件)位元組碼的動態生成。
cglib是一個工具,使用它你需要引入依賴:maven依賴如下
<dependency> <groupId>net.sourceforge.cglib</groupId> <artifactId>com.springsource.net.sf.cglib</artifactId> <version>2.1.3</version> </dependency>
cglib是通過構建目標類的子類,然後子類攔截父類方法來實現代理的。使用cglib,目標類不需要繼承介面。
1.你的類
public class Goods{
public void show() {
System.out.println("這是一個類");
}
}
2.代理類,繼承介面MethodInterceptor
預設情況會代理Goods的全部方法,你可在這裡新增一條判斷來決定代理哪些方法。
public class Poxy implements MethodInterceptor {
//代理方法
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("---擴充套件了方法---:"+method.getName());
System.out.println("---執行前擴充套件");
Object invoke=methodProxy.invokeSuper(o,objects);
System.out.println("---執行後擴充套件");
return invoke;
}
}
方法的返回值不知道是什麼,沒法獲取該物件的類,返回null也不影響正常代理
開始代理
public class Main {
public static void main(String[] args) {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(Goods.class); //繼承目標類
enhancer.setCallback(new Poxy()); //設定回撥
Goods goods= (Goods) enhancer.create(); //獲取goods
goods.show();
}
}
實現: