一、代理模式介紹
代理模式:為其他對象提供一種代理以便控制對這個對象的訪問。
可以詳細控制訪問某個類(對象)的方法,在調用這個方法前作的前置處理(統一的流程代碼放到代理中處理)。調用這個方法后做后置處理。
例如:明星的經紀人,租房的中介等等都是代理
代理模式分類:
1.靜態代理(靜態定義代理類,我們自己靜態定義的代理類。比如我們自己定義一個明星的經紀人類)
2.動態代理(通過程序動態生成代理類,該代理類不是我們自己定義的。而是由程序自動生成)比較重要!!
JDK自帶的動態代理
javaassist字節碼操作庫實現
CGLIB
ASM(底層使用指令,可維護性較差)
靜態代理模式結構圖:
靜態代理模式一般會有三個角色:
抽象角色:指代理角色(經紀人)和真實角色(明星)對外提供的公共方法,一般為一個接口
真實角色:需要實現抽象角色接口,定義了真實角色所要實現的業務邏輯,以便供代理角色調用。也就是真正的業務邏輯在此。
代理角色:需要實現抽象角色接口,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。
將統一的流程控制都放到代理角色中處理!
二、代理模式代碼實現
2.1 靜態代理模式
這里定義一個抽象角色接口(Star)、代理角色實現(ProxyStar)、真實角色實現(RealStar)
抽象角色接口:提供了與明星合作的一系列流程
1
2
3
4
5
6
7
8
9
10
11
12
|
package
com.fz.proxy.staticProxy;
/**
* 抽象角色:提供代理角色和真實角色對外提供的公共方法
*/
public
interface
Star {
void
confer();
//面談
void
signContract();
//簽合同
void
bookTicket();
//訂票
void
sing();
//唱歌
void
collectMoney();
//收尾款
}
|
代理角色實現類:代理角色中代理了真實角色所需要的操作(唱歌)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package
com.fz.proxy.staticProxy;
/**
* 代理角色(明星經紀人):
*/
public
class
ProxyStar
implements
Star{
private
Star star;
//真實對象的引用(明星)
@Override
public
void
confer() {
System.out.println(
"ProxyStar.confer()"
);
}
@Override
public
void
signContract() {
System.out.println(
"ProxyStar.signContract()"
);
}
@Override
public
void
bookTicket() {
System.out.println(
"ProxyStar.bookTicket()"
);
}
@Override
public
void
sing() {
star.sing();
//真實對象的操作(明星唱歌)
}
@Override
public
void
collectMoney() {
System.out.println(
"ProxyStar.collectMoney()"
);
}
public
ProxyStar(Star star) {
//通過構造器給真實角色賦值
this
.star = star;
}
}
|
真實角色實現類:這里的真實角色中其實只做了一個唱歌的操作,這是真實角色真正的業務邏輯部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package
com.fz.proxy.staticProxy;
/**
* 真實角色(明星藝人):
*/
public
class
RealStar
implements
Star{
@Override
public
void
confer() {
System.out.println(
"RealStar.confer()"
);
}
@Override
public
void
signContract() {
System.out.println(
"RealStar.signContract()"
);
}
@Override
public
void
bookTicket() {
System.out.println(
"RealStar.bookTicket()"
);
}
@Override
public
void
sing() {
System.out.println(
"張學友.sing()"
);
//真實角色的操作:真正的業務邏輯
}
@Override
public
void
collectMoney() {
System.out.println(
"RealStar.collectMoney()"
);
}
}
|
測試代理類:
1
2
3
4
5
6
7
8
9
|
public
static
void
main(String[] args) {
Star real =
new
RealStar();
Star proxy =
new
ProxyStar(real);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
//真實對象的操作(明星唱歌)
proxy.collectMoney();
}
|
輸出結果為:
ProxyStar.confer()
ProxyStar.signContract()
ProxyStar.bookTicket()
張學友.sing() //這里是真實角色的業務邏輯處理
ProxyStar.collectMoney()
以上代碼UML圖如下:
2.2 動態代理代碼實現
動態代理是不需要定義代理角色的,通過一個處理器來處理代理角色的業務邏輯。
抽象角色接口:提供了與明星合作的一系列流程
1
2
3
4
5
6
7
8
9
10
11
12
|
package
com.fz.proxy.staticProxy;
/**
* 抽象角色:提供代理角色和真實角色對外提供的公共方法
*/
public
interface
Star {
void
confer();
//面談
void
signContract();
//簽合同
void
bookTicket();
//訂票
void
sing();
//唱歌
void
collectMoney();
//收尾款
}
|
真實角色實現類:這里的真實角色中其實只做了一個唱歌的操作,這是真實角色真正的業務邏輯部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package
com.fz.proxy.staticProxy;
/**
* 真實角色(明星藝人):
*/
public
class
RealStar
implements
Star{
@Override
public
void
confer() {
System.out.println(
"RealStar.confer()"
);
}
@Override
public
void
signContract() {
System.out.println(
"RealStar.signContract()"
);
}
@Override
public
void
bookTicket() {
System.out.println(
"RealStar.bookTicket()"
);
}
@Override
public
void
sing() {
System.out.println(
"張學友.sing()"
);
//真實角色的操作:真正的業務邏輯
}
@Override
public
void
collectMoney() {
System.out.println(
"RealStar.collectMoney()"
);
}
}
|
代理角色的處理器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package
com.fz.proxy.dynamicProxy;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
/**
* 處理器
*/
public
class
StarHandler
implements
InvocationHandler{
private
Star realStar;
//真實角色
/**
* 所有的流程控制都在invoke方法中
* proxy:代理類
* method:正在調用的方法
* args:方法的參數
*/
@Override
public
Object invoke(Object proxy, Method method, Object[] args)
throws
Throwable {
Object object =
null
;
System.out.println(
"真實角色調用之前的處理....."
);
if
(method.getName().equals(
"sing"
)) {
object = method.invoke(realStar, args);
//激活調用的方法
}
System.out.println(
"真實角色調用之后的處理....."
);
return
object;
}
//通過構造器來初始化真實角色
public
StarHandler(Star realStar) {
super
();
this
.realStar = realStar;
}
}
|
測試代理模式:
1
2
3
4
5
6
7
8
9
|
public
static
void
main(String[] args) {
//真實角色
Star realStar =
new
RealStar();
//處理器
StarHandler handler =
new
StarHandler(realStar);
//代理類
Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new
Class[]{Star.
class
}, handler);
proxy.sing();
//調用代理類的唱歌方法:其實調用的是真實角色的唱歌方法
}
|
參考資料:
大話設計模式(帶目錄完整版).pdf
HEAD_FIRST設計模式(中文版).pdf
尚學堂_高淇_java300集最全視頻教程_【GOF23設計模式】