代理模式
代理模式允許你為其他對(duì)象提供一個(gè)代理,以控制對(duì)這個(gè)對(duì)象的訪問。代理模式在不改變實(shí)際對(duì)象的情況下,可以在訪問對(duì)象時(shí)添加額外的功能。
可以理解為代理模式為被代理對(duì)象創(chuàng)造了一個(gè)替身,調(diào)用者可以通過這個(gè)替身去實(shí)現(xiàn)這個(gè)被代理對(duì)象的功能,這個(gè)替身也可以為被代理對(duì)象增加功能
靜態(tài)代理
定義
使用時(shí)候需要定義接口或者父類。 代理類和委托類有共同的父類或父接口。
案例
首先定義一個(gè)接口?ITeacherDao,并在這個(gè)接口中定義一個(gè)teacher()方法。
package Static;
public interface ITeacherDao {
void teacher();
}
再寫一個(gè)他的實(shí)現(xiàn)類,實(shí)現(xiàn)teacher()方法
package Static;
public class TeacherDao implements ITeacherDao{
@Override
public void teacher() {
System.out.println("老師在教課");
}
}
?如上,我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單接口與他的實(shí)現(xiàn)類,接下來我們實(shí)現(xiàn)一個(gè)老師的靜態(tài)代理類
package Static;
public class TeacherDaoProxy implements ITeacherDao{
private TeacherDao teacherDao;
public TeacherDaoProxy(TeacherDao teacherDao){
this.teacherDao = teacherDao;
}
@Override
public void teacher() {
System.out.println("代理前");
teacherDao.teacher();
System.out.println("代理后");
}
}
在這段代碼中,我們實(shí)現(xiàn)了TeacherDao的代理類,并通過調(diào)用teacherDao這個(gè)對(duì)象使用了被代理對(duì)象的方法;我們?cè)谑褂帽淮韺?duì)象方法前后都拓展了新的功能,這就是靜態(tài)代理。
下面是主函數(shù)對(duì)于靜態(tài)代理的使用
public class Main {
public static void main(String[] args) {
Static.TeacherDao teacherDao = new TeacherDao();
TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
teacherDaoProxy.teacher();
}
}
?這說明我們的代理類在實(shí)現(xiàn)被代理對(duì)象的功能時(shí)也拓展了新的功能
但是,這樣的模式也存在一種缺陷,就是我們的代理對(duì)象和被調(diào)用對(duì)象都要實(shí)現(xiàn)同一接口或父類,可能會(huì)出現(xiàn)多個(gè)代理類,接口如果要增加方法的話會(huì)有很多代理類需要維護(hù);針對(duì)這一問題,Java的開發(fā)者定義了相關(guān)方法去解決,這就是我們下面要介紹的被代理類。
動(dòng)態(tài)代理
定義
不需要實(shí)現(xiàn)接口,但是被代理的目標(biāo)對(duì)象需要實(shí)現(xiàn),調(diào)用jdk的api形成代理對(duì)象,
動(dòng)態(tài)代理就是通過使用反射,動(dòng)態(tài)地獲取抽象接口的類型,從而獲取相關(guān)特性進(jìn)行代理。
案例
我們還是先定義一個(gè)接口
public interface ITeacherDao {
void teacher();
void sayhello();
}
接著我們定義他的實(shí)現(xiàn)類
public class TeacherDao implements ITeacherDao {
@Override
public void teacher() {
System.out.println("老師在教課");
}
@Override
public void sayhello() {
System.out.println("hello");
}
}
接著我們實(shí)現(xiàn)一個(gè)動(dòng)態(tài)的代理類,可以動(dòng)態(tài)代理原對(duì)象;在這個(gè)代理類中,我們使用到了Proxy.newProxyInstance 這個(gè)函數(shù),他有三個(gè)參數(shù),以下是三個(gè)參數(shù)的解釋
1.target.getClass().getClassLoader()
:獲取被代理對(duì)象的類加載器。這是用于加載代理類的類加載器。
2.target.getClass().getInterfaces()
:獲取被代理對(duì)象實(shí)現(xiàn)的接口。這些接口是代理類將要實(shí)現(xiàn)的接口。
3.new InvocationHandler() { ... }
:創(chuàng)建一個(gè)匿名的 InvocationHandler 對(duì)象,它實(shí)現(xiàn)了invoke
方法,這是代理邏輯的核心部分。
?我們?cè)?code>InvocationHandler() { ... }中調(diào)用了被代理對(duì)象的方法,并且做了一些擴(kuò)展
public class FactoryProxy {
private Object target;
public FactoryProxy(Object target){
this.target = target;
}
public Object getProxyIstance() {
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("代理前");
Object returnVal = method.invoke(target,args);
System.out.println("代理后");
return returnVal;
}
});
};
}
在主函數(shù)中調(diào)用被代理類,創(chuàng)建一個(gè)接口類,講接口類傳入被代理類,然后就可以定義接口類中的方法了,即實(shí)現(xiàn)了動(dòng)態(tài)代理。
public class Main {
public static void main(String[] args) {
ITeacherDao iteacherDao = new TeacherDao();
ITeacherDao proxyInstance = (ITeacherDao) new FactoryProxy(iteacherDao).getProxyIstance();
proxyInstance.teacher();
proxyInstance.sayhello();
}
}
最終輸出結(jié)果
?可以看出,我們通過動(dòng)態(tài)代理類實(shí)現(xiàn)了對(duì)目標(biāo)對(duì)象的功能拓展文章來源:http://www.zghlxwxcb.cn/news/detail-646275.html
鏈接
java靜態(tài)代理與動(dòng)態(tài)代理: java靜態(tài)代理與動(dòng)態(tài)代理文章來源地址http://www.zghlxwxcb.cn/news/detail-646275.html
到了這里,關(guān)于Java代理模式——靜態(tài)代理與動(dòng)態(tài)代理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!