文章目錄
- 代理模式
- 靜态代理模式
- 1、介紹
- 2、例子:婚介公司
- 3、優點
- 動态代理模式
- 1、介紹
- 2、例子:租房中介公司
- 3、優點
代理模式
靜态代理模式
1、介紹
1、真實角色和代理角色要實作同一個接口
2、代理角色要代理真實角色
3、給代理角色添加set方法(屬性為接口,進而解耦合),将某個真實角色注入到代理角色的屬性中,以便調用
2、例子:婚介公司
public class StaticProxyTest {
public static void main(String[] args) {
You you = new You();
WeddingCompany weddingCompany = new WeddingCompany();
weddingCompany.setMarry(you);
/*
這也是多線程Thread的原理
new Thread(一個實作Runnable接口的類).start(),而且Thread本身也實作了Runnable接口
*/
weddingCompany.HappyMarry();
}
}
interface Marry {
void HappyMarry();
}
//真實角色,你去結婚
class You implements Marry {
@Override
public void HappyMarry() {
System.out.println("Marry~");
}
}
//代理角色,幫你結婚
class WeddingCompany implements Marry {
private Marry target;
public void setMarry(Marry target) {
//傳入真實角色
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry(); //真實角色
after();
}
private void before() {
System.out.println("before--arrangement~");
}
private void after() {
System.out.println("after--clear~");
}
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAnYldHL0FWby9mZvwFN4ETMfdHLkVGepZ2XtxSZ6l2clJ3LcV2Zh1Wa9M3clN2byBXLzN3btgHL9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CN2YTMzUWOjljMwY2NhFjNzYzX4QjMxcDMyAzLcFTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
3、優點
代理角色可以做真實角色分外的事,進而真實角色專注做自己分内的事
動态代理模式
1、介紹
- 動态代理的角色和靜态代理的一樣
- 動态代理的代理類是動态生成的,靜态代理的代理類是我們提前寫好的
-
動态代理分為兩類 : 一類是基于接口動态代理 , 一類是基于類的動态代理
(1)基于接口的動态代理----JDK動态代理
(2)基于類的動态代理----cglib
(3)現在用的比較多的是 javasist 來生成動态代理 . 百度一下javasist
JDK的動态代理需要了解兩個類:
- InvocationHandler
-
【代理模式】靜态代理,動态代理 - Proxy
-
【代理模式】靜态代理,動态代理
2、例子:租房中介公司
public class DynamicProxyTest {
public static void main(String[] args) {
//真實角色
Host host = new Host();
//代理執行個體的調用處理程式
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setRent(host); //将真實角色放置進去!
Rent proxy = (Rent)pih.getProxy(); //動态生成對應的代理類!
proxy.rent();
}
}
//接口
interface Rent {
public void rent();
}
//真實角色: 房東,房東要出租房子
class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
//代理角色:中介
class ProxyInvocationHandler implements InvocationHandler {
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理類,重點是第二個參數,擷取要代理的抽象角色!之前都是一個角色,現在可以代理一類角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
// proxy : 代理類 method : 代理類的調用處理程式的方法對象.
// 處理代理執行個體上的方法調用并傳回結果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
//核心:本質利用反射實作!
Object result = method.invoke(rent, args);
fare();
return result;
}
//看房
public void seeHouse(){
System.out.println("帶房客看房");
}
//收中介費
public void fare(){
System.out.println("收中介費");
}
}
更有普适性的例子(優化了 ProxyInvocationHandler 類):
public class DynamicProxyTest {
public static void main(String[] args) {
//真實角色
Host host = new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(host); //将真實角色放置進去!
Rent proxy = (Rent)pih.getProxy(); //動态生成對應的代理類!
proxy.rent();
}
}
//接口
interface Rent {
public void rent();
}
//真實角色: 房東,房東要出租房子
class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
//代理角色:中介
class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
// proxy : 代理類
// method : 代理類的調用處理程式的方法對象.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String methodName){
System.out.println("執行了"+methodName+"方法");
}
}
3、優點
- 可以使得我們的真實角色更加純粹 . 不再去關注一些公共的事情
- 公共的業務由代理來完成 . 實作了業務的分工
- 公共業務發生擴充時變得更加集中和友善
- 一個動态代理 , 一般代理某一類業務
- 一個動态代理可以代理多個類,代理的是接口