初学 Java 设计模式(十一):实战外观模式 「类型转换器」
一、外觀模式介紹
1. 解決的問題
主要解決訪問復雜系統的內部子系統的復雜度問題,簡化客戶端與其子系統的接口。
2. 定義
外觀模式是一種結構型設計模式,能為程序庫、框架或其他復雜類提供一個簡單的接口。
3. 應用場景
- 需要一個指向復雜子系統的直接接口,且該接口的功能有限,可以使用外觀模式。
- 需要將子系統組織為多層結構,可以使用外觀模式。
二、外觀模式優缺點
1. 優點
- 可以讓代碼獨立于復雜子系統。
2. 缺點
- 外觀可能成為與程序中所有類都耦合的上帝對象。
三、外觀模式應用實例:類型轉換器
1. 實例場景
在我們的工作中,常常會遇到一些類型轉換的問題,比如將一個數組轉換成字符串等,我們通常會用一些第三方工具類庫來實現,比如 Hutool ,這種工具類庫其實就是包含外觀模式的思想,我們無需關注內部如何實現類型轉換,只需根據方法說明傳參即可獲取我們想要的轉換結果。
今天就以類型轉換為例,介紹一下如何使用外觀模式。
2. 外觀模式實現
2.1 工程結構
facade-pattern └─ src├─ main│ └─ java│ └─ org.design.pattern.facade│ ├─ convert│ │ └─ Convert.java│ ├─ converter│ │ └─ StringConverter.java│ ├─ text│ │ └─ ASCIIStrCache.java│ └─ utils│ ├─ ArrayUtil.java│ └─ CharUtil.java└─ test└─ java└─ org.design.pattern.facade.test└─ ConvertTest.java2.2 代碼實現
2.2.1 Facade
/*** 類型轉換*/ public class Convert {/*** 轉換為字符串* 如果給定的值為null,或者轉換失敗,返回null* 轉換失敗不會報錯** @param value 被轉換的值* @return String*/public static String toString(Object value) {return StringConverter.convertToStr(value);} }2.2.2 轉換器
字符串轉換器
/*** 字符串轉換器*/ public class StringConverter {/*** 數據轉為String* 轉換規則為:* 1、字符串類型將被強轉* 2、數組將被轉換為逗號分隔的字符串* 3、其它類型將調用默認的toString()方法** @param value 數據* @return String*/public static String convertToStr(Object value) {if (null == value) {return null;}if (value instanceof CharSequence) {return value.toString();} else if (ArrayUtil.isArray(value)) {return ArrayUtil.toString(value);} else if(CharUtil.isChar(value)) {//對于ASCII字符使用緩存加速轉換,減少空間創建return CharUtil.toString((char)value);}return value.toString();} }2.2.3 文本操作
ASCII字符串緩存
/*** ASCII字符串緩存*/ public class ASCIIStrCache {private static final int ASCII_LENGTH = 128;private static final String[] CACHE = new String[ASCII_LENGTH];static {for (char c = 0; c < ASCII_LENGTH; c++) {CACHE[c] = String.valueOf(c);}}/*** 字符轉為字符串* 如果為ASCII字符,使用緩存** @param c 字符* @return 字符串*/public static String toString(char c) {return c < ASCII_LENGTH ? CACHE[c] : String.valueOf(c);} }2.2.4 工具類
數組工具類
/*** 數組工具類*/ public class ArrayUtil {/*** 對象是否為數組對象** @param obj 對象* @return 是否為數組對象,如果為空 返回false*/public static boolean isArray(Object obj) {if (null == obj) {return false;}return obj.getClass().isArray();}/*** 數組或集合轉String** @param obj 集合或數組對象* @return 數組字符串,與集合轉字符串格式相同*/public static String toString(Object obj) {if (null == obj) {return null;}if (obj instanceof long[]) {return Arrays.toString((long[]) obj);} else if (obj instanceof int[]) {return Arrays.toString((int[]) obj);} else if (obj instanceof short[]) {return Arrays.toString((short[]) obj);} else if (obj instanceof char[]) {return Arrays.toString((char[]) obj);} else if (obj instanceof byte[]) {return Arrays.toString((byte[]) obj);} else if (obj instanceof boolean[]) {return Arrays.toString((boolean[]) obj);} else if (obj instanceof float[]) {return Arrays.toString((float[]) obj);} else if (obj instanceof double[]) {return Arrays.toString((double[]) obj);} else if (ArrayUtil.isArray(obj)) {// 對象數組try {return Arrays.deepToString((Object[]) obj);} catch (Exception e) {// 不操作}}return obj.toString();} }字符工具類
/*** 字符工具類*/ public class CharUtil {/*** 給定對象對應的類是否為字符類,字符類包括:* Character.class* char.class** @param value 被檢查的對象* @return true表示為字符類*/public static boolean isChar(Object value) {// noinspection ConstantConditionsreturn value instanceof Character || value.getClass() == char.class;}/*** 字符轉為字符串* 如果為ASCII字符,使用緩存** @param c 字符* @return 字符串*/public static String toString(char c) {return ASCIIStrCache.toString(c);} }2.3 測試驗證
2.3.1 測試驗證類
/*** 轉換測試類*/ public class ConvertTest {private final Logger log = LoggerFactory.getLogger(ConvertTest.class);@Testpublic void testConvertString() {int number = 1;log.info("int number = 1 convert string : " + Convert.toString(number));char charString = 'a';log.info("char charString = 'a' convert string : " + Convert.toString(charString));long[] array = {1,2,3,4,5};log.info("long[] array = {1,2,3,4,5} convert string : " + Convert.toString(array));} }2.3.2 測試結果
14:50:51.514 [main] INFO o.d.pattern.facade.test.ConvertTest - int number = 1 convert string :1 14:50:51.517 [main] INFO o.d.pattern.facade.test.ConvertTest - char charString = 'a' convert string :a 14:50:51.517 [main] INFO o.d.pattern.facade.test.ConvertTest - long[] array = {1,2,3,4,5} convert string :[1, 2, 3, 4, 5]Process finished with exit code 0四、外觀模式結構
外觀(Facade)提供了一種訪問特定子系統功能的便捷方式,其了解如何重定向客戶端請求,知曉如何操作一切活動不見。
創建附加外觀(Additional Facade)類可以避免多種不相關的功能污染單一外觀,使其變成又一個復雜結構。客戶端和其他外觀都可使用附加外觀。
復雜子系統(Complex Subsystem)有數十個不同對象構成。如果要用這些對象完成有意義的工作,必須了解子系統的實現細節,比如按照正確順序初始化對象和為其提供正確格式的數據。
子系統類不會意識到外觀的存在,它們在系統內運作并且相互之間可直接進行交互。
客戶端(Client)使用外觀代替對子系統對象的直接調用。
設計模式并不難學,其本身就是多年經驗提煉出的開發指導思想,關鍵在于多加練習,帶著使用設計模式的思想去優化代碼,就能構建出更合理的代碼。
源碼地址:https://github.com/yiyufxst/design-pattern-java
參考資料:
小博哥重學設計模式:https://github.com/fuzhengwei/itstack-demo-design
深入設計模式:https://refactoringguru.cn/design-patterns/catalog
總結
以上是生活随笔為你收集整理的初学 Java 设计模式(十一):实战外观模式 「类型转换器」的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鸿蒙开发套件全面升级,助力鸿蒙生态蓬勃发
- 下一篇: python画六角图_六角图