諾基亞在美國推出 G20 手機:Helio G35 晶片,價格 199 美元
阿新 • • 發佈:2021-06-25
代理模式
定義:由於某些原因需要給某物件提供一個代理以控制該物件的訪問
結構:
- 抽象主題(Subject): 介面宣告要實現的業務方法
- 真實主題 (Real Subject): 實現抽象主題裡的業務方法
- 代理類(Proxy):提供了與真實主題相同的介面,它可以擴充套件、控制真實主題的功能。
代理模式的結構很簡單,是通過繼承抽象主題的代理類來包含真實主題,從而來實現對真實主題的訪問。
程式碼示例:
public interface Ticket {
void buyTicket();
}
public class OfficialTicket implements Ticket { @Override public void buyTicket() { System.out.println("官方途徑購票"); } }
public class ProxyTicket implements Ticket {
private OfficialTicket officialTicket=new OfficialTicket();
@Override
public void buyTicket() {
System.out.println("我把錢給了去哪網,委託購票");
officialTicket.buyTicket();
}
}
測試程式碼:
public static void main(String[] args) throws InterruptedException, CloneNotSupportedException { ProxyTicket proxyTicket = new ProxyTicket(); proxyTicket.buyTicket();
以上就是代理模式的實現,也可以說是靜態代理
靜態代理的侷限性:
- 如果我們需要再增加一個需要代理的方法,那我們需要修改上面3個類,每個類都要加對應的邏輯。
- 如果我們想再代理一個其他的物件,也需要對代理類進行修改。
那麼如果用動態代理實現上面的程式碼會怎麼樣呢?
Ticket類和OfficialTicket不變
public class TicketInvocationHandler implements InvocationHandler { private Ticket ticket; public TicketInvocationHandler(Ticket ticket) { this.ticket = ticket; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我把錢給了去哪網,委託購票"); method.invoke(ticket,args); return null; } }
測試程式碼:
public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
Ticket ticket = new OfficialTicket();
//將操作者物件進行注入
TicketInvocationHandler handler = new TicketInvocationHandler(ticket);
//生成代理物件
Ticket operationProxy = (Ticket) Proxy.newProxyInstance(ticket.getClass().getClassLoader(),
ticket.getClass().getInterfaces(), handler);
operationProxy.buyTicket();
}
此時如果我們想增加一個退票方法,如果用動態代理,那麼只需要改動Ticket類和OfficialTicket類。
Cglib實現:
public class TicketMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("我把錢給了去哪網,委託購票");
Object object = proxy.invokeSuper(obj, args);
return object;
}
}
測試程式碼:
public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
Enhancer enhancer = new Enhancer();
// 設定enhancer物件的父類
enhancer.setSuperclass(OfficialTicket.class);
// 設定enhancer的回撥物件
enhancer.setCallback(new TicketMethodInterceptor());
// 建立代理物件
Ticket proxy= (Ticket)enhancer.create();
// 通過代理物件呼叫目標方法
proxy.buyTicket();
}