1. 程式人生 > 遊戲 >《賽博朋克2077》新補丁正在測試 大型更新或將上線

《賽博朋克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();
    }
}

實現:
在這裡插入圖片描述