什麼是代理模式 舉個例子,我是一個包租公,我現在想賣房,但是我不想麻煩,每天被電話騷擾,所以這個時候我找了樓下一個中介,讓他幫我代理這些事,那麼他自然有租房的方法。以後如果有人想租房,直接找中介就行了。 為什麼用代理模式 從上面的代碼可以看出,代理類(SaleProxy)和真實類(Jiajun)好像 ...
什麼是代理模式
舉個例子,我是一個包租公,我現在想賣房,但是我不想麻煩,每天被電話騷擾,所以這個時候我找了樓下一個中介,讓他幫我代理這些事,那麼他自然有租房的方法。以後如果有人想租房,直接找中介就行了。
public interface Sale {
public void sale();
}
public class Jiajun implements Sale{
public void sale() {
// TODO 自動生成的方法存根
System.out.println("jiajun要賣房");
}
}
public class SaleProxy implements Sale{
Jiajun jiajun=new Jiajun();
@Override
public void sale() {
// TODO 自動生成的方法存根
jiajun.sale();
}
}
public Client{
public static void main(String[] args)
{
Sale saleProxy=new SaleProxy();
saleProxy.sale();
}
}
為什麼用代理模式
從上面的代碼可以看出,代理類(SaleProxy)和真實類(Jiajun)好像沒什麼區別,我直接(new Jiajun().sale())不就行了,那麼為什麼多次一舉呢,任何設計都有他的好處。我們可以發現代理類可以在真實類的基礎上增加方法,比如這個時候中介可以收取買主的費用。
public class SaleProxy implements Sale{
Jiajun jiajun=new Jiajun();
@Override
public void sale() {
// TODO 自動生成的方法存根
charge();
jiajun.sale();
}
public void charge()
{
System.out.println("jiajun要賣房,中介要收費");
}
}
而這個不關我事,中介你幫我租出去就行。
什麼是動態代理模式
靜態代理模式有他的缺點:
如果這個時候,我要做的事情增多了,比如我在賣房的時候,我還可以租房。那麼我在Sale介面要增加一個方法,真實類(Jiajun)要實現多一個方法,此時代理類(SaleProxy)又要實現多一個方法,如果以後要拓展,會增加很多方法,那麼就增加維護難度。
public interface Sale { public void sale(); public void rent(); } public class SaleProxy implements Sale{ Jiajun jiajun=new Jiajun(); @Override public void sale() { // TODO 自動生成的方法存根 jiajun.sale(); } public void rent() { jiajun.rent(); } }
如果真實類(Jiajun)實現了多個介面,我要為多種方法代理,那麼我要手動創建很多代理類。
比如這裡我實現了兩個介面。
public interface Sale {
public void sale();
}
public interface Buy {
public void buy();
}
public class Jiajun implements Sale,Buy{
public void sale() {
// TODO 自動生成的方法存根
System.out.println("jiajun要賣房");
}
public void buy() {
// TODO 自動生成的方法存根
System.out.println("jiajun要買房");
}
}
這個時候我要生成兩個代理,那麼我就要創建兩個代理類
public class BuyProxy implements Buy{
Jiajun jiajun=new Jiajun();
public void buy() {
// TODO 自動生成的方法存根
jiajun.buy();
}
}
public class SaleProxy implements Sale{
Jiajun jiajun=new Jiajun();
@Override
public void sale() {
// TODO 自動生成的方法存根
jiajun.sale();
}
}
public class Client {
public static void main(String[] args) {
Sale saleProxy=new SaleProxy();
saleProxy.sale();
Buy buyProxy=new BuyProxy();
buyProxy.buy();
}
}
如果我要為多種方法代理,那麼就會產生很多代理類。
針對這些缺點,動態代理出現了
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyHandler implements InvocationHandler{
private Object tar;
//綁定委托對象,並返回代理類
public Object bind(Object tar)
{
this.tar=tar;
//綁定該類實現的所有介面,取得代理類
return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy , Method method , Object[] args)throws Throwable
{
Object result = null;
result = method.invoke(tar,args);
return result;
}
}
public class Client {
public static void main(String[] args) {
ProxyHandler proxy = new ProxyHandler();
//綁定該類實現的所有介面
Sale saleProxy = (Sale) proxy.bind(new Jiajun());
saleProxy.sale();;
Buy buyProxy=(Buy)proxy.bind(new Jiajun());
buyProxy.buy();
}
}
顯然,上面的缺點得到解決了。
- 即使介面增加方法,我也不用在代理類再實現一次。
- 即使我要對不同方法做代理,我也不用創建一個代理類文件。
- 動態代理類由Java反射機制動態生成,不用我們自己生成(這裡我們並沒有看到買房代理類,賣房代理類文件)
- 動態代理類不僅簡化了編程工作,而且提高了軟體系統的可擴展性,因為Java 反射機制可以生成任意類型的動態代理類。(我們要買房代理就買房代理,賣房代理就賣房代理,比較靈活)。
- 總的來說,關鍵的就是我們避免了代理類文件的編寫,從而提高了許多便利。
- 至於動態代理是怎麼實現的,需要瞭解一下反射,後面會繼續更新。