最易懂設(shè)計(jì)模式解析
適配器設(shè)計(jì)模式
模板方法設(shè)計(jì)模式
Mybatis多級代理
1. 認(rèn)識代理模式
1.1 模式定義
給某一個對象提供一個代理或占位符耐朴,并由代理對象來控制對原對象的訪問借卧。
代理模式是一種對象結(jié)構(gòu)型模式。在代理模式中引入了一個新的代理對象筛峭,代理對象在客戶端對象和目標(biāo)對象之間起到中介的作用铐刘,它去掉客戶不能看到的內(nèi)容和服務(wù)或者增添客戶需要的額外的新服務(wù)。
1.2 解決何種問題
將【次要業(yè)務(wù)】和【主要業(yè)務(wù)解耦合】影晓。
核心就是代理對象(Proxy)镰吵。
1.3次要業(yè)務(wù)和主要業(yè)務(wù)
1.3.1 它們之間的區(qū)分
次要業(yè)務(wù):輔助【主要業(yè)務(wù)】順利實(shí)現(xiàn)。在項(xiàng)目中【次要業(yè)務(wù)】往往大量重復(fù)出現(xiàn)挂签。
主要業(yè)務(wù):主要任務(wù)疤祭。
1.3.2 次要業(yè)務(wù)對于開發(fā)效率影響
- 加載驅(qū)動類《牛【次要業(yè)務(wù)】
- 建立連接通道画株。【次要業(yè)務(wù)】
- 建立數(shù)據(jù)庫操作對象啦辐∥酱【次要業(yè)務(wù)】
- 推送sql命令道數(shù)據(jù)庫執(zhí)行并返回處理結(jié)果∏酃兀【主要業(yè)務(wù)】
- 銷毀connection,statement,resultSet续挟。【次要業(yè)務(wù)】
1.4 代理模式的本質(zhì)
控制對象訪問(行為的監(jiān)聽)
<input type="button" onclick="fun1">
onclick行為監(jiān)聽對象(代理對象proxy)對 button 單擊的行為調(diào)用了fun1方法(InvovationHandler)
1.5 代理模式的組成
- 接口:聲明需要被監(jiān)聽行為侥衬。
- 代理實(shí)現(xiàn)類:次要業(yè)務(wù)實(shí)現(xiàn)诗祸、將次要業(yè)務(wù)和主要業(yè)務(wù)綁定執(zhí)行跑芳。
- 代理對象(監(jiān)聽對象)
2. 實(shí)例講解
2.1 實(shí)例業(yè)務(wù)介紹
飯前便后要洗手
【主要業(yè)務(wù)】:吃飯、便便直颅。
【次要業(yè)務(wù)】:洗手博个。
2.2 具體實(shí)現(xiàn)
創(chuàng)建一個接口BaseService
//被監(jiān)控的行為
public interface BaseService {
//吃飯方法
public void eating(String food);
//上廁所方法
public void wcing();
}
代理實(shí)現(xiàn)類Agent
public class Agent implements InvocationHandler {
private BaseService obj;// 被開發(fā)人員索要的真實(shí)對象
//完成次要業(yè)務(wù)和主要業(yè)務(wù)綁定
public Agent(BaseService param) {
this.obj = param;
}
/*
* Object proxy:本次負(fù)責(zé)監(jiān)聽對象----onclick
*
* Method method: 被攔截的主要業(yè)務(wù)方法
*
* Object[] params:被攔截的主要業(yè)務(wù)方法接受的實(shí)參
*/
@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
//1.讀取被攔截的方法名稱
String methodName = method.getName();
if("eating".equals(methodName)){//飯前要洗手
wash();
method.invoke(obj, params);
}else{//便后要洗手
method.invoke(obj, params);
wash();
}
return null;
}
//次要業(yè)務(wù)
private void wash(){
System.out.println("洗手");//解耦合;
}
創(chuàng)建接口實(shí)現(xiàn)類功偿,Person實(shí)現(xiàn)了BaseService中的方法是需要被監(jiān)聽的方法
public class Person implements BaseService {
@Override
public void eating(String food) {
System.out.println("狼吞虎咽吃 "+food);
}
@Override
public void wcing() {
System.out.println("減體重...");
}
}
創(chuàng)建一個代理工廠ProxyFactory
public class ProxyFactory {
//扮演一個角色(吃和拉的監(jiān)聽對象)
public static BaseService newInstance(Class classFile) throws InstantiationException, IllegalAccessException{
//0.創(chuàng)建被索要的類型的實(shí)例對象
BaseService 小明 = new Person();
//1.擁有一個代理實(shí)現(xiàn)類對象
InvocationHandler agent = new Agent(小明);//小明被囚禁到了Agent中
//2.申請/注冊一個對特定行為進(jìn)行監(jiān)控對象(代理對象)
/*
* loader:指向被監(jiān)控的類文件在內(nèi)存中真實(shí)地址
* interfaces(classArray): 被監(jiān)控的類所實(shí)現(xiàn)的接口盆佣,這個接口中聲明的方法,就是需要被監(jiān)控行為也是主要業(yè)務(wù)行為名稱
*/
Class classArray[]={BaseService.class}; //這個接口里所有的方法都要被監(jiān)聽
//創(chuàng)建一個代理監(jiān)聽對象
BaseService 監(jiān)聽對象=(BaseService) Proxy.newProxyInstance(Person.class.getClassLoader(), classArray, agent);
return 監(jiān)聽對象; //返回的是一個假貨(披著羊皮的狼) 監(jiān)聽對象
}
測試類
public class TestMain {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
//BaseService 小明 = new Person();//丑陋的行為 不受監(jiān)控的對象
BaseService 小明 = ProxyFactory.newInstance();
小明.eating("雞");
}
}
測試結(jié)果
洗手
狼吞虎咽吃 雞