前言
本篇依然使用Java作為核心語言來總結<u>結構型模式</u>, 重點使用UML類圖以減少來回切換代碼而引起的邏輯混亂性.
完整代碼已上傳至GitOSC
適配器模式 - Adapter
適配器模式是將其他接口的功能進行轉換, 本質是轉調已有功能. 相對于裝飾者模式, 適配器模式轉換后的接口會變, 裝飾者則保持同一個接口, 所以裝飾者模式適合遞歸.
下面是將Android手機適配為假iPhone的例子
UML
適配器模式
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
// 我們有一臺普通的安卓手機
final AndroidPhone androidPhone = new AndroidPhone();
// 被奸商拿去改成iPhone騙小白
final IPhoneAdaptor iPhone = new IPhoneAdaptor(androidPhone);
// 視頻通話時瑪德黑屏
iPhone.videoCall();
}
}
橋接模式 - Bridge
維基上的對該模式的描述如下
Decouple an abstraction from its implementation allowing the two to vary independently.
讀起來不太像人話, "從實現部分解耦出抽象部門, 使他們可以獨立變化"
其實我們平常寫的Service, ServiceImpl就是橋接模式. 橋接模式適合控制多種變量, 例如"中國人發短信", "中國發郵件", "美國人發短信", "美國人發郵件". 這里有兩個變量"人"和"發布信息的方式", 這樣就抽象成兩個Service了.
UML
橋接模式
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
final MessageService messageService = new EmailMessageService();
final UserService userService = new ChineseService(messageService);
userService.giveBirth();
}
}
裝飾者模式 - Decorator
裝飾者模式主要功能是以動態的透明的方式給對象添加職責, 如增強功能, 控制訪問
下面是對MacBook添加Touch Bar并添加顏色Space Grey的例子
UML
裝飾者模式
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
final MacBook macBook = new MacBook();
final TouchBarDecorator greyMacBook = new TouchBarDecorator(macBook);
final SpaceGreyDecorator touchBar = new SpaceGreyDecorator(greyMacBook);
System.out.println(touchBar.feature());
}
}
外觀模式 - Facade
為多個組件提供一個同一的接口, 使系統更加易用.
外觀模式正是體現迪米特法則, 客戶端只需要外觀類進行交互, 屏蔽了底層模塊.
下面是Apple被夷為平地和Dell破產的例子
UML
外觀模式
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
new TroubleFacade().boom();
}
}
代理模式
此處僅介紹Java中的動態代理, 這里就直接看代碼
/**
* @author Zhao Junjian
*/
public class MacBookProxy implements InvocationHandler {
private Laptop target;
public Laptop getProxy(MacBook macBook) {
this.target = macBook;
return (Laptop) Proxy.newProxyInstance(
macBook.getClass().getClassLoader(),
macBook.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("dynamic proxy");
return method.invoke(target, args);
}
}
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
final MacBook macBook = new MacBook();
final Laptop proxy = new MacBookProxy().getProxy(macBook);
// shutdown()是Laptop中的方法
proxy.shutdown();
}
}
作者:Chris
原博客:http://blog.chriscs.com