Java設(shè)計模式之代理模式解析
代理模式(Proxy)
代理模式的基本介紹
1.代理模式:為一個對象提供一個替身,以控制對這個對象的訪問,即通過代理對象訪問目標(biāo)對象…這樣做的好處是:可以在目標(biāo)對象實現(xiàn)的基礎(chǔ)上,增強額外的功能操作,即擴展目標(biāo)對象的功能
2.被代理對象可以使遠(yuǎn)程對象、創(chuàng)建開銷大的對象或需要安全控制的對象
3.代理模式有不同的形式,主要有三種靜態(tài)代理、動態(tài)代理(JDK代理、接口代理)、和cglib代理(可以在內(nèi)存中動態(tài)的創(chuàng)建對象,而不需要實現(xiàn)接口,它是屬于動態(tài)代理的范疇)
靜態(tài)代理
靜態(tài)代理在使用時,需要定義接口或者父類,被代理對象(即目標(biāo)對象)與代理對象一起實現(xiàn)相同的接口或者是繼承相同父類
應(yīng)用實例
1、定義一個接口ITeacherDao
2.目標(biāo)對象TeacherDao實現(xiàn)ITeacherDao
3.使用靜態(tài)代理方式,就需要在代理對象TeacherDaoProxy中也實現(xiàn)ITeacherDao
4.調(diào)用的時候通過調(diào)用代理對象的方法來調(diào)用目標(biāo)對象
5.特別提醒:代理對象與目標(biāo)對象要實現(xiàn)相同的接口,然后通過調(diào)用相同的方法來 調(diào)用目標(biāo)對象方法
接口
/**
* 接口
*/
public interface ITeacherDao {
/**
* 授課的方法
*/
void teach();
}接口實現(xiàn)
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("老師授課中......");
}
}代理類實現(xiàn)接口
/**
* 代理類 靜態(tài)代理
* @create: 2021/10/6
* @author: Tony Stark
*/
public class TeacherDaoProxy implements ITeacherDao {
/**
*目標(biāo)對象通過接口來聚合
*/
private ITeacherDao target;
/**
* 構(gòu)造器 構(gòu)建TeacherDaoProxy對象是傳進(jìn)來一個接口 (實現(xiàn)了接口的具體子類對象)
* @param target
*/
public TeacherDaoProxy(ITeacherDao target) {
this.target = target;
}
@Override
public void teach() {
//加入增強的方法
System.out.println("代理開始 完成一些操作.......");
//執(zhí)行代理類的方法
target.teach();
//增強的步驟
System.out.println("提交操作 代理結(jié)束.......");
}
}調(diào)用
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class Client {
public static void main(String[] args) {
//被代理的對象
TeacherDao teacherDao = new TeacherDao();
//代理對象 把背代理對象傳給代理對象
TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
//通過代理對象執(zhí)行方法
teacherDaoProxy.teach();
}
}輸出
代理開始 完成一些操作.......
老師授課中......
提交操作 代理結(jié)束.......
靜態(tài)代理優(yōu)缺點:
1.優(yōu)點:在不修改目標(biāo)對象的功能的前提下,能通過代理對象對目標(biāo)功能擴展
2.缺點:因為代理對象需要與目標(biāo)對象實現(xiàn)一樣的接口,所以會有很多代理類
3.一旦接口增加方法 就要修改所有
動態(tài)代理
1.動態(tài)代理,不需要實現(xiàn)接口,但是目標(biāo)對象要實現(xiàn)接口,否則不能用動態(tài)代理
2.代理對象的生成,是利用JDK的API,動態(tài)的在內(nèi)存中構(gòu)建代理對象
3.動態(tài)代理也叫做:JDK代理、接口代理
JDK中生成代理對象API
1.代理類所在包:java.lang.reflect.Proxy
2.JDK實現(xiàn)代理只需要使用newProxyInstance方法,但是該方法需要接收三個參數(shù),完整的寫法是
static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
我們把上面的靜態(tài)代理改成動態(tài)代理

接口
/**
* 接口
*/
public interface ITeacherDao {
/**
* 授課的方法
*/
void teach();
}實現(xiàn)類
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("老師正在授課...");
}
}代理
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class ProxyFactory {
/**
*維護(hù)一個目標(biāo)對象
*/
private Object target;
/**
* 構(gòu)造器對target進(jìn)行初始化
* @param target
*/
public ProxyFactory(Object target) {
this.target = target;
}
/**
* 給目標(biāo)對象生成一個代理對象
* @return
*/
public Object getProxyInstance(){
//參數(shù)說明:
//ClassLoader loader 指定當(dāng)前目標(biāo)對象使用的類加載器 獲取加載器的方法固定
//Class<?>[] interfaces 目標(biāo)對象(被代理對象)的接口類型 使用泛型的方式確認(rèn)類型
//target.getClass().getInterfaces()獲取所有接口
//InvocationHandler h 事件處理,執(zhí)行目標(biāo)對象方法時
// 會觸發(fā)事件處理器的方法,會把當(dāng)前執(zhí)行的目標(biāo)對象方法作為參數(shù)傳入
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK代理開始");
//通過反射調(diào)用目標(biāo)對象的方法
Object invoke = method.invoke(target, args);
return invoke;
}
});
}
}調(diào)用測試
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class Client {
public static void main(String[] args) {
//創(chuàng)建目標(biāo)對象
ITeacherDao target = new TeacherDao();
//給目標(biāo)對象創(chuàng)建代理對象
ProxyFactory proxyFactory = new ProxyFactory(target);
//返回的是代理對象 一個Object 可以強轉(zhuǎn)成ITeacherDao 不強轉(zhuǎn)調(diào)不了方法
ITeacherDao proxyInstance = (ITeacherDao) proxyFactory.getProxyInstance();
//從這里可以看出內(nèi)存中動態(tài)生成了代理對象 class com.sun.proxy.$Proxy0
System.out.println(proxyInstance.getClass());
proxyInstance.teach();
}
}輸出
class com.sun.proxy.$Proxy0
JDK代理開始
老師正在授課...
到此這篇關(guān)于Java設(shè)計模式之代理模式解析的文章就介紹到這了,更多相關(guān)Java代理模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
舉例說明JAVA調(diào)用第三方接口的GET/POST/PUT請求方式
在日常工作和學(xué)習(xí)中,有很多地方都需要發(fā)送請求,這篇文章主要給大家介紹了關(guān)于JAVA調(diào)用第三方接口的GET/POST/PUT請求方式的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
使用curator實現(xiàn)zookeeper鎖服務(wù)的示例分享
這篇文章主要介紹了使用curator實現(xiàn)zookeeper鎖服務(wù)的示例,需要的朋友可以參考下2014-02-02
mybatis-plus報錯net.sf.jsqlparser.statement.select.SelectBody的
本文主要介紹了mybatis-plus報錯net.sf.jsqlparser.statement.select.SelectBody的問題解決,具有一定的參考價值,感興趣的可以了解一下2024-08-08

