7.javaSE基礎進階_設計模式和代理模式(靜態代理JDK和動態代理CGLIB)

文章目錄

  • 一.設計模式
    • 1.簡介
      • 1)設計模式基本要素
      • 2)設計模式的分類
        • 1.模式依據其目的可分為:
        • 2.第二是范圍準則
        • 3.創建模式
        • 4.結構模式
        • 5、行為模式
    • 2.工廠模式
      • 1)定義
      • 2)結構
      • 3)創建工廠
    • 3.單例(Singleton)模式
      • 1)定義
      • 2)應用
      • 3)分類
        • 1.餓漢式EngerSingLeton
        • 2.懶漢式LazySingLeton
    • 4.Prototype模式
      • 1)適應場景
      • 2)結構
  • ...................................................................................................
  • 二.代理模式
    • 1.簡介
      • 1)定義:
      • 2)**分類**
      • 3)Proxy模式結構
    • 2.靜態代理
      • 1)優缺點
    • 3.動態代理
      • 1)JDK原生動態代理
      • 2)CGLIB動態代理
    • 4.JDK代理與CGLIB代理的區別

一.設計模式

1.簡介

設計模式是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。

  • 使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。
  • 每個模式描述了一個在我們周圍不斷重復發生的問題,以及該問題的解決方案的核心。
  • 設計模式的貫穿思想:針對接口編程,最大限度的適應變化,實現代碼重用

1)設計模式基本要素

  • 模式名稱(pattern name):一個助記名, 它用一兩個詞來描述模式的問題、解決方案和效果。
  • **問題(problem):**描述了應該在何時使用模式它解釋了設計問題和問題存在的前因后果,它可能描述了特定的設計問題,如怎樣用對象表示算法等。
  • **解決方案(solution):**描述了設計的組成成分,它們之間的相互關系及各自的職責和協作方式。
  • 效果(consequences) : 描述了模式應用的效果及使用模式應權衡的問題。

2)設計模式的分類

1.模式依據其目的可分為:
  • 創建型(Creational) 創建型模式與對象的創建有關
  • 結構型 (Structural) 結構型模式處理類或對象的組合
  • 行為型(Behavioral) 行為型模式對類或對象怎樣交互和怎樣分配職責進行描述
2.第二是范圍準則

指定模式主要是用于類還是用于對象。

  • 類模式:處理類和子類之間的關系,這些關系通過繼承建立,是靜態的,在編譯時刻便確定下來了。
  • 對象模式:處理對象間的關系,這些關系在運行時刻是可以變化的,更具動態性。
3.創建模式

創建模式(Creational Pattern):是對類的實例化過程的抽象化

一些系統在創建對象時,需要動態地決定怎樣創建對象、創建哪些對象,創建模式描述了怎樣構造和封裝這些動態的決定:

  • 工廠方法(Factory Method)
  • 抽象工廠(Abstract Factory)
  • 單例(Singletion)
  • 原型(Prototype)
  • 建造者(Builder)
4.結構模式

結構模式(Structural Pattern):描述如何將類或者對象結合在一起形成更大的結構,結構模式描述了兩種不同的東西:類、類的實例

  • 適配器(Adapter)
  • 橋接(Bridge)
  • 組合(Composite)
  • 裝飾(Decorator)
  • 外觀(Facade)
  • 享元(Flyweight)
  • 代理(Proxy)
5、行為模式

在不同的對象之間劃分責任和算法,而且解決對象之間如何相互作用

  • 迭代(Iterator)
  • 模板方法(Template Method)
  • 職責鏈(Chain of Responsibility)
  • 訪問者(Visitor)
  • 中介者(Mediator)
  • 觀察者(Observer)
  • 備忘錄(Memento)
  • 狀態(State)
  • 策略(Strategy)
  • 命令(Command)
  • 解釋器(Interpreter)

2.工廠模式

1)定義

工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

工廠模式又叫靜態工廠方法模式、簡單工廠

2)結構

模式的核心是工廠類。這個類含有必要的判斷邏輯,可以決定在什么時候創建那一個產品類的實例。而客戶端則可以免除直接創建產品對象的責任,而僅僅負責“消費”產品。簡單工廠模式通過這種做法實現了對責任的分割

  • 工廠類(Creator)角色:擔任這個角色的是工廠模式的核心,含有與應用緊密相關的商業邏輯。工廠類在客戶端的直接調用下創建產品對象,它往往由一個具體Java類實現。
  • 抽象產品(Product)角色:擔任這個角色的類是由工廠方法模式所創建的對象的父類,或它們共同擁有的接口。抽象產品角色可以用一個Java接口或者java抽象類實現。
  • 具體產品(Concrete Product)角色:工廠方法模式所創建的任何對象都是這個角色的實例,具體產品角色有一個具體java類實現

創建測試接口及實現類,

3)創建工廠

通過中間的工廠調用其他類的方法

3.單例(Singleton)模式

1)定義

單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。

這里有三個要點:

  1. 某個類只能有一個實例
  2. 類必須自行創建這個實例
  3. 以公共、統一的方式向整個系統提供這個實例

2)應用

許多時候整個系統只需要擁有一個的全局對象,這樣有利于我們協調系統整體的行為。

比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然后服務進程中的其他對象再通過這個單例對象獲取這些配置信息。

這種方式簡化了在復雜環境下的配置管理

借助編程語言自身的語法特性,強制限制某個類,不能創建多個實例

3)分類

1.餓漢式EngerSingLeton

直接創建對象

public class EagerSingleton {private static final EagerSingleton m_instance = new EagerSingleton();
?private EagerSingleton() {}
?public static EagerSingleton getInstance() {return m_instance;}
}
2.懶漢式LazySingLeton

先判斷在創建對象

public class LazySingleton {private static LazySingleton m_instance = null;
?private LazySingleton() {}
?public static LazySingleton getInstance() {if (m_instance == null) {m_instance = new LazySingleton();}return m_instance;}
}

4.Prototype模式

Prototype模式即原型模式,原型模式其實是一個比較單純的設計模式,其目的就是利用一個原型對象,快速地生成一批對象,從而避免重復的新建過程。

工作原理是:通過將一個原型對象傳給一個要新建的對象,新建對象通過請求原型對象拷貝它們,然后自己來實施創建

1)適應場景

主要適用于以下情況:

  • 構建函數相對比較復雜
  • 構建函數不能被不相關的人調用
  • 一批對象中絕大部分對象的屬性一致,而只有極少數不同

2)結構

  • Prototype:聲明一個克隆自身的接口或抽象類
  • ConcretePrototype:實現一個克隆自身的操作
  • Client:讓一個原型來克隆自身從而創建一個新的對象

二.代理模式

1.簡介

代理這個詞相信大家并不陌生,我們大家都知道代理商,簡單地說就是代替廠家賣商品,廠家委托代理為其銷售商品,顧客找代理購買商品。

通過使用代理,通常有兩個優點,并且能夠分別與我們提到的代理商的幾個特點對應起來:

  1. 關于代理商,首先我們從他們那里買東西時通常不知道背后的廠家究竟是誰,也就是說,委托者對我們來說是不可見的;
  2. 代理可以對顧客進行定位,更精確的售賣給需要的客戶群體

1)定義:

代理模式是常用的java設計模式,他的特征是代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事后處理消息等。

代理類與委托類之間通常會存在關聯關系,一個代理類的對象與一個委托類的對象關聯,代理類的對象本身并不真正實現服務,而是通過調用委托類的對象的相關方法,來提供特定的服務。

代理模式:為其他對象提供一種代理以控制對這個對象的訪問,也就是創建一個代理對象作為客戶端和目標對象之間的中介,主要目的就是保護目標對象或增強目標對象

通過使用代理模式,通常有以下兩個優點:

  1. 可以隱藏被代理類的實現
  2. 可以實現客戶與被代理類間的解耦,在不修改被代理類代碼的情況下能夠做一些額外的處理

2)分類

按照代理的創建時期,代理類可以分為兩種。

  • 靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了**
  • 動態代理:在程序運行時,運用反射機制動態創建而成

3)Proxy模式結構

由三部分組成:

  • Proxy:保存一個引用使得代理可以訪問實體。控制對實體的存取,并可能負責創建和刪除它,其他功能依賴于代理的類型。
  • Subject:定義RealSubject和Proxy的共用接口,這樣就在任何使用RealSubject的地方都可以使用Proxy。
  • RealSubject:定義Proxy所代表的實體。

2.靜態代理

若代理類在程序運行前就已經存在,那么這種代理方式被成為 靜態代理 ,這種情況下的代理類通常都是我們在Java代碼中定義的

所謂的靜態代理,就是通過聲明一個明確的代理類來訪問源對象,一個代理只能服務于一種產品,當有n種產品時,就需要n個代理,這樣就不利于業務的發展。

舉例:我們有兩個接口,Computer和 Phone,每個接口都有一個實現類

  1. 定義接口(代理接口)
  2. 定義實現類(委托類)
  3. 定義代理類Proxy(代理類,最終還是調用委托類實現業務操作)

通過代理類調用的方法調用實現類的方法

1)優缺點

靜態代理的代碼非常簡單易懂,這種模式雖好,但是也有明顯的缺點:

  • 會存在大量冗余的代理類,這里只有兩個接口,如果有n個接口,那么就要定義n個代理類。
  • 不易維護,一旦接口更改,代理類和被代理類都要更改。

3.動態代理

代理類在程序運行時創建的代理方式被成為 動態代理。 也就是說,這種情況下,代理類并不是在Java代碼中定義的,而是在運行時根據我們在Java代碼中的指示動態生成的 ,在程序運行時,運用反射機制動態創建而成代理對象。

JDK從1.3版本就開始支持動態代理類的創建。

java.lang.reflect類庫中提供三個類直接支持代理模式:ProxyInvocationHandlerMethod

1)JDK原生動態代理

是Java原生支持的,不需要外部依賴,但是它只能基于接口進行代理(需要動態代理的對象必須實現與某個接口)

  1. Proxy類

    Proxy 提供用于創建動態代理類和實例的靜態方法,它還是由這些方法創建的所有動態代理類的超類。

    核心方法newProxyInstance:返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)//參數說明:
//loader - 定義代理類的類加載器 interfaces - 代理類要實現的接口列表 h - 指派方法調用的調用處理程序
//Ps:類加載器 在Proxy類中的newProxyInstance()方法中需要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器
  1. InvocationHandler類

    代理實例的調用處理程序 實現的接口

    每個代碼實例都具有一個關聯的調用處理程序。對代理實例調用方法時,將對方法調用進行編碼并將其指派到它的調用處理程序的 invoke 方法

package java.lang.reflect;
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}
//參數說明:
//Object proxy:在其上調用方法的代理實例。
//Method method:要調用的方法
//Object\[] args:方法調用時所需要的參數
//可以將InvocationHandler接口的子類想象成一個代理的最終操作類,替換掉ProxySubject。
public class JDKProxy implements InvocationHandler {private final Object target;public JDKProxy(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long start = System.currentTimeMillis();Object obj = method.invoke(target, args);long end = System.currentTimeMillis();System.out.println(method.getName() + "耗時" + (end - start) + "ms");return obj;}
  1. Method類

    Method 提供關于類或接口上單獨某個方法(以及如何訪問該方法)的信息。所反映的方法可能是類方法或實例方法(包括抽象方法)。

    主要方法invoke:對帶有指定參數的指定對象調用由此 Method 對象表示的基礎方法

public Object invoke(Object obj,Object... args)
//  參數: obj - 從中調用基礎方法的對象 args - 用于方法調用的參數

2)CGLIB動態代理

[CGLIB] https://mvnrepository.com/artifact/cglib/cglib CGLIB

CGLIB通過繼承的方式進行代理,(讓需要代理的類成為Enhancer的父類),無論目標對象有沒有實現接口都可以代理,但是無法處理Final的情況(依賴外包)

  • 引入依賴

    導入cglib-3.1.jarasm-4.2.jar

  • 使用流程

    1. 創建代理對象

    2. 得到委托類

    3. 得到代理類

    4. 通過代理對象調用方法

public class CGLibProxy {public static Object getProxy(final Object target) {//創建enhancer對象Enhancer enhancer = new Enhancer();//創建代理對象為超級類enhancer.setSuperclass(target.getClass());//調用應用enhancer.setCallback(new MethodInterceptor() {/*** @author Arran* @description  * @params [o, method, objects, methodProxy] * @return java.lang.Object * @date  2024/06/27 下午 03:13*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("售前咨詢 之前被調用");Object result = method.invoke(target, objects);System.out.println("售后處理 之后被調用");return result;}});//創建代理對象return enhancer.create();}
}

4.JDK代理與CGLIB代理的區別

  • JDK動態代理實現接口,CGLIB動態繼承思想

  • JDK動態代理(目標對象存在接口時)執行效率高于CIGLIB

  • 如果對象有接口實現,選擇JDK代理,如果沒有接口實現選擇CGILB代

?

 Object result = method.invoke(target, objects);System.out.println("售后處理 之后被調用");return result;}});//創建代理對象return enhancer.create();
}

}


## 4.JDK代理與CGLIB代理的區別- JDK動態代理實現接口,CGLIB動態繼承思想- JDK動態代理(目標對象存在接口時)執行效率高于CIGLIB- 如果對象有接口實現,選擇JDK代理,如果沒有接口實現選擇CGILB代?     

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/37433.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/37433.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/37433.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java學習 - Redis緩存問題與優化

緩存收益與成本 收益 加速讀寫降低后端、持久層的負載和壓力 成本 可能導致數據不一致代碼運維成本redis節點運維成本 緩存更新策略 策略一致性維護成本介紹LRU/LIRS算法剔除最差底剔除最近最少使用的數據超時剔除較差底定時刪除、惰性刪除主動更新最好高持久層更新&#x…

監控 Promethus的監控告警Alertmanager、Grafana

Promethus的監控告警Alertmanager Alertmanager 介紹 Prometheus的一個組件&#xff0c;用于定義和發送告警通知&#xff0c;內置多種第三方告警通知方式&#xff0c;同時還提供了對Webhook通知的支持基于警報規則對規則產生的警報進行分組、抑制和路由&#xff0c;并把告警發…

深入了解Spring框架的模塊組成

目錄 Spring CoreSpring ContextSpring AOPSpring DAOSpring ORMSpring WebSpring MVCSpring WebFluxSpring TestSpring BootSpring SecuritySpring BatchSpring IntegrationSpring Cloud結論 Spring Core 1.1 核心容器 Spring Core模塊是整個Spring框架的基礎。它包含了框架…

vue如何引入圖標

方法1&#xff1a;iconify/vue pnpm add iconify/vue -D 網址&#xff1a;https://icon-sets.iconify.design/ 使用哪個需要安裝 如下截圖,安裝指令&#xff1a; > npm install iconify/icons-gg在使用的頁面引入 import { Icon } from “iconify/vue”; <template>…

Mysql存儲過程用法:使用存儲過程編程,來判斷數據庫中數據表中的字段是否重復,避免重復插入記錄

目錄 一、mysql的存儲過程介紹 二、. 創建存儲過程 1、準備 2、創建插入記錄的存儲過程 三. 調用存儲過程 四. 刪除存儲過程 五. 修改存儲過程&#xff0c;避免數據表的姓名出現重復 1、修改存儲過程的方式 2、重新創建存儲過程 六. 驗證新的存儲過程 1、插入新的記…

高考后的抉擇:專業優先還是學校優先?

隨著2024年高考的帷幕落下&#xff0c;高考生們面臨的一個重要抉擇再度浮上心頭&#xff1a;在分數受限的情況下&#xff0c;是選擇一個心儀的專業&#xff0c;還是選擇一個知名度更高的學校&#xff1f;這是一個困擾了眾多考生和家長的長期難題。在這個關鍵的時刻&#xff0c;…

好用的導航網站有哪些

網址導航網站是我們日常上網的一個重要工具。它們不僅可以幫助我們快速找到所需的資源和信息&#xff0c;還能提高我們的工作效率。以下是小編收藏的幾個好用的導航網站&#xff0c;涵蓋了辦公、學習、娛樂等多個領域&#xff0c;分享給大家。 1. 辦公人導航 辦公人導航是一個…

Drag Select Compose:實現多平臺圖片多選功能的利器

Drag Select Compose:實現多平臺圖片多選功能的利器 在現代移動應用開發中,圖片多選功能是一個常見且實用的需求。而實現這種功能可能涉及到復雜的手勢處理和狀態管理。今天,我將介紹一款強大的Compose多平臺庫——Drag Select Compose,它能夠輕松實現類似于Google Photos…

【鴻蒙】第2天?裝飾器?組件和頁面生命周期

背景知識 &#xff11;?ArkTS 拓展了 TypeScript&#xff0c;TypeScript 拓展了 JavaScript。 增加了一些約束。 &#xff12;?ArkTS 是聲明式編程。 構建對象時類似構建者設計模式。鏈式賦值。 裝飾器 &#xff20;Component 自定義組件 Component裝飾器僅能裝飾str…

BGP中的TCP連接源地址問題

3.TCP連接源地址&#xff08;用loop back地址是最優選擇&#xff09; 應用場景與理論&#xff1a; 由于BGP應用于大型網絡中&#xff0c;為了避免單點失敗&#xff0c;往往需要通過多條鏈路連接&#xff0c;當一條鏈路故障時候就用另一條鏈路繼續工作&#xff0c;但是BGP又無法…

為何重要?解析企業實行網絡安全等級保護的必要性

在全球信息化迅速發展的背景下&#xff0c;企業數據資產成為核心競爭力的重要組成部分。然而&#xff0c;隨之而來的網絡安全威脅亦日益嚴峻&#xff0c;從數據泄露到勒索軟件攻擊&#xff0c;每一次安全事件都可能給企業帶來不可估量的損失。在此情境下&#xff0c;實行網絡安…

Java IO: 使用 FileReader 和 FileWriter 進行文件操作

在 Java 中&#xff0c;進行文件操作是一個常見的任務。FileReader 和 FileWriter 是用于讀取和寫入文本文件的類&#xff0c;它們提供了一種方便的方法來處理文件內容。本文將介紹如何使用 FileReader 和 FileWriter&#xff0c;并提供一些示例代碼。 FileReader 類概述 Fil…

使用PHP創建一個簡單的Web爬蟲

隨著互聯網的不斷發展&#xff0c;信息的獲取變得越來越方便。然而&#xff0c;海量的信息也給我們帶來了很多的煩惱&#xff0c;如何高效地獲取到我們所需要的信息就成了一項非常重要的任務。在實現自動化獲取信息的過程中&#xff0c;web爬蟲被廣泛應用。 Web爬蟲是一種自動…

R語言進行字符的替換和刪減gsub,substr函數

目錄 R語言讀文件“-“變成“.“ 提取列字符前幾個 提取列字符末尾幾個 進行字母替換 paste0函數使用</

學計算機的學生假期可以干什么?

學習目標&#xff1a; 學計算機的學生假期可以干什么 學習內容&#xff1a; 實習&#xff1a;尋找計算機相關領域的實習機會&#xff0c;積累工作經驗。這對你未來找工作非常有幫助。在線課程&#xff1a;參加編程、數據科學或其他技術領域的在線課程&#xff0c;提升技能。公…

python實現API調用緩存

python實現API調用緩存 1.代碼2.輸出3.保存的json數據 想把python某些函數的參數及返回值記錄下來,如果之前已計算過,則直接返回緩存中的數據 1.代碼 import jsondef get_variable_name(var):變量轉變量名local_varsglobals()return [name for name, value in local_vars.ite…

螺旋模型:結合瀑布模型和增量模型的項目管理利器

目錄 前言1. 螺旋模型概述1.1 螺旋模型的核心理念1.2 螺旋模型的四個階段 2. 螺旋模型的詳細步驟2.1 計劃階段2.2 風險分析階段2.3 工程階段2.4 評估階段 3. 螺旋模型在大型項目中的應用3.1 應對需求變化3.2 有效的風險管理3.3 增強的客戶參與3.4 靈活的資源分配 4. 螺旋模型的…

redis分布式事務

1. 使用RedisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS) 這種方法是基于Redis的SET命令的NX&#xff08;Not eXists&#xff09;選項和EX&#xff08;expiry time&#xff09;選項來實現的。它嘗試設置一個鍵值對&#xff0c;只有當鍵不存在時才…

git-extras

當使用 git-extras 時&#xff0c;除了安裝和基本命令之外&#xff0c;了解如何結合常見的 Git 工作流程和實際開發需求會更加有幫助。下面是一個更全面的 git-extras 使用教程&#xff0c;涵蓋了安裝、常見命令以及實際應用場景的示例。 1. 安裝 git-extras 在 macOS 上&…

Java面試題:討論單例模式的實現方式,包括懶漢式和餓漢式,并討論線程安全問題

單例模式&#xff08;Singleton Pattern&#xff09;是一種設計模式&#xff0c;確保一個類只有一個實例&#xff0c;并提供一個全局訪問點。單例模式在某些場景下很有用&#xff0c;例如配置管理、日志記錄等。以下是單例模式的兩種主要實現方式&#xff1a;懶漢式&#xff08…