這個模式其實(shí)是
Adapter
模式和Decorator
模式的統(tǒng)稱脑又。
1. 范例
Servlet規(guī)范中的javax.servlet.http.HttpServletRequestWrapper
就是這種模式的經(jīng)典例子倔矾。
-
HttpServletRequestWrapper
繼承自ServletRequestWrapper
, 同時實(shí)現(xiàn)了HttpServletRequest
旅敷。 - 而
ServletRequestWrapper
則是實(shí)現(xiàn)了ServletRequest
接口瞎惫。 - 注意
HttpServletRequestWrapper
和ServletRequestWrapper
都不是abstract, 所以是可以直接拿來用的。 不過我們一般是繼承自它榆骚,然后覆寫我們所關(guān)注的方法蕉汪。
2. 分析
因?yàn)檫@些wrapper可以互相嵌套, 最終造就一個千層餅樣式的對象封字。每一層都是
ServletRequest
類型黔州, 但每層只處理特定的一個需求, 這樣就將一個瑞士軍刀類里的功能分散了出去阔籽。每層餅增強(qiáng)原來瑞士軍刀類的一部分功能流妻, 這樣就會將原來的瑞士軍刀類的功能集拆分為一個個非常小的功能塊, 每個功能小塊只專注特定的一部分仿耽。 如果劃分得好的話合冀, 相當(dāng)于將瑞士軍刀類進(jìn)行了邏輯切割。類的數(shù)量增多, 但代碼量減小项贺,便于維護(hù)和升級。
而且Wrapper模式下峭判,對于同一個方法开缎,各個Wrapper實(shí)例的包裝順序和其執(zhí)行順序是正好相反的。
3. 代碼講解
// All -- 瑞士軍刀類
public class All {
public void a(){
System.out.println("a");
}
public void b(){
System.out.println("b");
}
public void c(){
System.out.println("c");
}
public void X(){
System.out.println("ALL - X");
}
}
// Wrapper模式
public abstract class AllWrapper extends All {
private All under;
protected AllWrapper(All all) {
under = all;
}
@Override
public void a() {
under.a();
}
@Override
public void b() {
under.b();
}
@Override
public void c() {
under.c();
}
@Override
public void X() {
under.X();
}
}
// ----------------- 以下的 A, B, C只關(guān)注于某個方法林螃。
// 專注于 a 功能塊的處理
public class A extends AllWrapper {
protected A(All all) {
super(all);
}
@Override
public void a() {
System.out.println("A - a");
}
@Override
public void X() {
System.out.println("A - X");
super.X();
}
}
// 專注于 b 功能塊的處理
public class B extends AllWrapper {
protected B(All all) {
super(all);
}
@Override
public void b() {
System.out.println("B - b");
}
@Override
public void X() {
System.out.println("B - X");
super.X();
}
}
// 專注于 c 功能塊的處理
public class C extends AllWrapper {
protected C(All all) {
super(all);
}
@Override
public void c() {
System.out.println("C - c");
}
@Override
public void X() {
System.out.println("C - X");
super.X();
}
}
// 單元測試
public class DesignPattern_Wrapper_Tests {
@Test
public void testname() throws Exception {
All all = new All();
// a
// b
// c
all.a();
all.b();
all.c();
all = new A(all);
all = new B(all);
all = new C(all);
// A - a
// B - b
// C - c
// 可以嘗試注釋掉上面的某一行代碼, 查看輸出結(jié)果
all.a();
all.b();
all.c();
// ----- 和上面的注入順序正好相反
// C - X
// B - X
// A - X
// ALL - X
all.X();
}
}
4. 總結(jié)
這種文章本來應(yīng)該是入行一兩年的時候就寫下的奕删。之所以推遲到了現(xiàn)在,一言難盡啦疗认!