日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java后端分享整理

發布時間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java后端分享整理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

java規范總結

  • 1. Java 常見的代碼規范
    • 1.1. Java 自帶的工具方法
      • 1.1.1 比較兩個對象是否相等
      • 1.1.2 apache commons工具類庫
        • 1.1.2.1 字符串判空
        • 1.1.2.3 重復拼接字符串
        • 1.1.2.4 格式化日期
        • 1.1.2.4 包裝臨時對象 (不是特別常用)
      • 1.1.3 common-beanutils 操作對象
      • 1.1.3.1 commons-io 文件流處理
      • 1.1.4 Google Guava 工具類庫
        • 1.1.4.1 創建集合
    • 1.2 java 常見的代碼規范
      • 1.2.1 使用Collection.isEmpty() 檢測空
      • 1.2.2 初始化集合時盡量指定其大小
      • 1.2.3 若需頻繁調用Collection.contains 方法則使用Set
      • 1.2.4 使用靜態代碼塊實現賦值靜態成員變量
      • 1.2.5 工具類中屏蔽構造函數
      • 1.2.6 刪除未使用的局部變量、方法參數、私有方法、字段和多余的括號
      • 1.2.8 字符串轉化使用String.valueOf(value) 代替 " " + value (需補充)
      • 1.2.9 避免使用BigDecimal(double)
  • 2. 設計模式
    • 2.1 裝飾者模式訂閱
      • 2.1.1 定義
      • 2.1.2職責
      • 2.1.3 裝飾模式結構
      • 2.1.3 舉一個簡單的例子
      • 2.1.4 另一個很經典的一個場景
      • 2.1.5 需求抽象出來
      • 2.1.6 具體的類圖
      • 2.1.7 裝飾模式的優點
      • 2.1.8 缺點
    • 2.2 橋接者模式
      • 2.2.1 橋接模式概念
      • 2.2.2 結構圖
      • 2.2.3 具體代碼
      • 2.2.4 橋接模式的設計要點和適用性
      • 2.2.5 裝飾模式和橋接模式的區別
    • 2.3 觀察者模式
    • 2.4 責任鏈模式
    • 2.5 建造者模式
      • 2.5.1 概念
    • 2.6 組合這模式
      • 2.6.1 組合模式的概念
      • 2.6.2 組合模式結構
      • 2.6.3組合模式工作分析
    • 2.7 策略模式
    • 2.8 外觀模式
      • 2.8.1 概念
    • 2.9 命令模式
      • 2.9.1 概念
      • 2.9.2 模式結構
      • 2.9.3 結構圖
      • 2.9.3建議看這個代碼
      • 2.9.4 命令模式的優缺點

感謝分享:

1. Java 常見的代碼規范

1.1. Java 自帶的工具方法

1.1.1 比較兩個對象是否相等

當我們用equals比較兩個對象是否相等的時候,還需要對左邊的對象進行判空,不然可能會報空指針異常,我們可以用java.util包下Objects封裝好的比較是否相等的方法:

Objects.equals(strA, strB);

源碼:

public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }

1.1.2 apache commons工具類庫

apache commons是最強大的,也是使用最廣泛的工具類庫,里面的子庫非常多,下面介紹幾個最常用的

commons-lang,java.lang的增強版 建議使用commons-lang3,優化了一些api,原來的commons-lang已停止更新:

maven 的依賴:

org.apache.commons commons-lang3 3.12.0

1.1.2.1 字符串判空

傳參CharSequence類型是String、StringBuilder、StringBuffer的父類,都可以直接下面方法判空,以下是源碼:

public static boolean isEmpty(final CharSequence cs) { return cs == null || cs.length() == 0; } public static boolean isNotEmpty(final CharSequence cs) { return !isEmpty(cs); } // 判空的時候,會去除字符串中的空白字符,比如空格、換行、制表符 public static boolean isBlank(final CharSequence cs) { final int strLen = length(cs); if (strLen == 0) { return true; } for (int i = 0; i < strLen; i++) { if (!Character.isWhitespace(cs.charAt(i))) { return false; } } return true; } public static boolean isNotBlank(final CharSequence cs) { return !isBlank(cs); }

####1.1.2.2 首字母轉大寫 (這里可以查詢源碼看其他stringUtils 提供的其他源碼,提供的新的特性)

String str = "yideng"; String capitalize = StringUtils.capitalize(str); System.out.println(capitalize); // 輸出Yideng

1.1.2.3 重復拼接字符串

String str = StringUtils.repeat("ab", 2); System.out.println(str); // 輸出abab

1.1.2.4 格式化日期

再也不用手寫SimpleDateFormat格式化了

// Date類型轉String類型 String date = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"); System.out.println(date); // 輸出 2021-05-01 01:01:01 // String類型轉Date類型 Date date = DateUtils.parseDate("2021-05-01 01:01:01", "yyyy-MM-dd HH:mm:ss"); // 計算一個小時后的日期 Date date = DateUtils.addHours(new Date(), 1);

1.1.2.4 包裝臨時對象 (不是特別常用)

當一個方法需要返回兩個及以上字段時,我們一般會封裝成一個臨時對象返回,現在有了Pair和Triple就不需要了

// 返回兩個字段 ImmutablePair<Integer, String> pair = ImmutablePair.of(1, "yideng"); System.out.println(pair.getLeft() + "," + pair.getRight()); // 輸出 1,yideng // 返回三個字段 ImmutableTriple<Integer, String, Date> triple = ImmutableTriple.of(1, "yideng", new Date()); System.out.println(triple.getLeft() + "," + triple.getMiddle() + "," + triple.getRight()); // 輸出 1,yideng,Wed Apr 07 23:30:00 CST 2021

1.1.3 commons-collections 集合工具類

封裝了集合判空的方法,以下是源碼:

public static boolean isEmpty(final Collection<?> coll) { return coll == null || coll.isEmpty(); } public static boolean isNotEmpty(final Collection<?> coll) { return !isEmpty(coll); } // 兩個集合取交集 Collection<String> collection = CollectionUtils.retainAll(listA, listB); // 兩個集合取并集 Collection<String> collection = CollectionUtils.union(listA, listB); // 兩個集合取差集 Collection<String> collection = CollectionUtils.subtract(listA, listB);

1.1.3 common-beanutils 操作對象

Maven依賴:

<dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.4</version> </dependency> public class User { private Integer id; private String name; }

設置對象屬性

User user = new User(); BeanUtils.setProperty(user, "id", 1); BeanUtils.setProperty(user, "name", "yideng"); System.out.println(BeanUtils.getProperty(user, "name")); // 輸出 yideng System.out.println(user); // 輸出 {"id":1,"name":"yideng"}

對象和map互轉

// 對象轉map Map<String, String> map = BeanUtils.describe(user); System.out.println(map); // 輸出 {"id":"1","name":"yideng"} // map轉對象 User newUser = new User(); BeanUtils.populate(newUser, map); System.out.println(newUser); // 輸出 {"id":1,"name":"yideng"}

1.1.3.1 commons-io 文件流處理

Maven依賴:

commons-io commons-io 2.8.0

文件處理

File file = new File("demo1.txt"); // 讀取文件 List<String> lines = FileUtils.readLines(file, Charset.defaultCharset()); // 寫入文件 FileUtils.writeLines(new File("demo2.txt"), lines); // 復制文件 FileUtils.copyFile(srcFile, destFile);

1.1.4 Google Guava 工具類庫

maven 依賴:

com.google.guava guava 30.1.1-jre

1.1.4.1 創建集合

List<String> list = Lists.newArrayList(); List<Integer> list = Lists.newArrayList(1, 2, 3); // 反轉list List<Integer> reverse = Lists.reverse(list); System.out.println(reverse); // 輸出 [3, 2, 1] // list集合元素太多,可以分成若干個集合,每個集合10個元素 List<List<Integer>> partition = Lists.partition(list, 10); Map<String, String> map = Maps.newHashMap(); Set<String> set = Sets.newHashSet();

1.2 java 常見的代碼規范

1.2.1 使用Collection.isEmpty() 檢測空

? 使用Collection.size() 來檢測是否為空在邏輯上沒有問題,但是使用Collection.isEmpty() 使得代碼更易讀,并且可以獲得更好的性能;除此之外,任何Collection.isEmpty() 實現的時間復雜度都是O(1) ,不需要多次循環遍歷,但是某些通過Collection.size() 方法實現的時間復雜度可能是O(n)。O(1)緯度減少循環次數 例子

反例:

LinkedList<Object> collection = new LinkedList<>(); if (collection.size() == 0){System.out.println("collection is empty.");}

正例

LinkedList<Object> collection = new LinkedList<>(); if (collection.isEmpty()){System.out.println("collection is empty.");}//檢測是否為null 可以使用CollectionUtils.isEmpty() if (CollectionUtils.isEmpty(collection)){System.out.println("collection is null.");

1.2.2 初始化集合時盡量指定其大小

盡量在初始化時指定集合的大小,能有效減少集合的擴容次數,因為集合每次擴容的時間復雜度很可能時O(n),耗費時間和性能。

反例

//初始化list,往list 中添加元素反例: int[] arr = new int[]{1,2,3,4}; List<Integer> list = new ArrayList<>(); for (int i : arr){ list.add(i); }

正例:

//初始化list,往list 中添加元素正例: int[] arr = new int[]{1,2,3,4}; //指定集合list 的容量大小List<Integer> list = new ArrayList<>(arr.length); for (int i : arr){ list.add(i);}

1.2.3 若需頻繁調用Collection.contains 方法則使用Set

在Java 集合類庫中,List的contains 方法普遍時間復雜度為O(n),若代碼中需要頻繁調用contains 方法查找數據則先將集合list 轉換成HashSet 實現,將O(n) 的時間復雜度將為O(1)。

反例:

//頻繁調用Collection.contains() 反例 List<Object> list = new ArrayList<>(); for (int i = 0; i <= Integer.MAX_VALUE; i++){ //時間復雜度為O(n) if (list.contains(i))System.out.println("list contains "+ i);}

正例:

//頻繁調用Collection.contains() 正例List<Object> list = new ArrayList<>();Set<Object> set = new HashSet<>(); for (int i = 0; i <= Integer.MAX_VALUE; i++){ //時間復雜度為O(1) if (set.contains(i)){System.out.println("list contains "+ i);}}

1.2.4 使用靜態代碼塊實現賦值靜態成員變量

對于集合類型的靜態成員變量,應該使用靜態代碼塊賦值,而不是使用集合實現來賦值。

反例:

//賦值靜態成員變量反例 private static Map<String, Integer> map = new HashMap<String, Integer>(){{ map.put("Leo",1); map.put("Family-loving",2); map.put("Cold on the out side passionate on the inside",3);}}; private static List<String> list = new ArrayList<>(){{ list.add("Sagittarius"); list.add("Charming"); list.add("Perfectionist");}};

正例:

//賦值靜態成員變量正例 private static Map<String, Integer> map = new HashMap<String, Integer>(); static { map.put("Leo",1); map.put("Family-loving",2); map.put("Cold on the out side passionate on the inside",3);}private static List<String> list = new ArrayList<>(); static { list.add("Sagittarius"); list.add("Charming"); list.add("Perfectionist");}

1.2.5 工具類中屏蔽構造函數

工具類是一堆靜態字段和函數的集合,其不應該被實例化;但是,Java 為每個沒有明確定義構造函數的類添加了一個隱式公有構造函數,為了避免不必要的實例化,應該顯式定義私有構造函數來屏蔽這個隱式公有構造函數。

反例:

public class PasswordUtils { //工具類構造函數反例 private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";public static String encryptPassword(String aPassword) throws IOException { return new PasswordUtils(aPassword).encrypt();}

正例:

public class PasswordUtils { //工具類構造函數正例 private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);//定義私有構造函數來屏蔽這個隱式公有構造函數 private PasswordUtils(){}public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";public static String encryptPassword(String aPassword) throws IOException { return new PasswordUtils(aPassword).encrypt();}

1.2.6 刪除未使用的局部變量、方法參數、私有方法、字段和多余的括號

### 1.2.7 **刪除多余的異常捕獲并拋出 ** (需補充)

用catch 語句捕獲異常后,若什么也不進行處理,就只是讓異常重新拋出,這跟不捕獲異常的效果一樣,可以刪除這塊代碼或添加別的處理。

//多余異常反例 private static String fileReader(String fileName)throws IOException{try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { String line;StringBuilder builder = new StringBuilder(); while ((line = reader.readLine()) != null) {builder.append(line);} return builder.toString();} catch (Exception e) { //僅僅是重復拋異常 未作任何處理 throw e;} }

正例:

//多余異常正例 private static String fileReader(String fileName)throws IOException{try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { String line;StringBuilder builder = new StringBuilder(); while ((line = reader.readLine()) != null) {builder.append(line);} return builder.toString(); //刪除多余的拋異常,或增加其他處理: /*catch (Exception e) {return "fileReader exception";}*/} }

1.2.8 字符串轉化使用String.valueOf(value) 代替 " " + value (需補充)

把其它對象或類型轉化為字符串時,使用String.valueOf(value) 比 “”+value 的效率更高。

反例:

//把其它對象或類型轉化為字符串反例: int num = 520; // "" + value String strLove = "" + num;

正例:

//把其它對象或類型轉化為字符串正例: int num = 520; // String.valueOf() 效率更高 String strLove = String.valueOf(num);

1.2.9 避免使用BigDecimal(double)

BigDecimal(double) 存在精度損失風險,在精確計算或值比較的場景中可能會導致業務邏輯異常。

反例:

// BigDecimal 反例 BigDecimal bigDecimal = new BigDecimal(0.11D);

正例:

// BigDecimal 正例 BigDecimal bigDecimal1 = bigDecimal.valueOf(0.11D);

2. 設計模式

2.1 裝飾者模式訂閱

2.1.1 定義

裝飾模式又稱,包裝模式。裝飾模式是以客戶端透明的方式擴展對象的功能 是一種繼承的替代方案。

2.1.2職責

  • 動態給對象增加新的功能
  • 裝飾模式是一種用于替代,繼承的技術,無需通過繼承增加子類就能擴展 對象的功能。使用對象的關聯關系,替代繼承關系 更加靈活,同時避免了體系的膨脹。

2.1.3 裝飾模式結構

  • 裝飾模式類圖

  • Component 抽象構建角色 :真是對象(對應上圖 ConcreteOperation() 對象)和裝飾對象具有相同的接口

    。這樣客戶端對象就能以與 真是對象相同的方式同裝飾對象交互了。

  • ConcreteComponent 具體構建的角色(真是對象) :定義一個接收附加責任的類。

  • Decorator裝飾角色 持有構建角色的引用。裝飾對象接收客戶端的請求,并把這些請求轉發給真是的對象。這樣,就能在真是對象調用前后增加新的功能。

  • ConcreteDecorate 具體的裝飾角色:負責給構建對象增加新的功能。

2.1.3 舉一個簡單的例子

舉一個簡單的汽車例子,創造每一種汽車都需要繼承父類進行實現,如下圖 那么當我們需要,既能路上行駛,又能水上行駛,又得繼承父類。

以后每增加一種新功能的汽車都需要增一個類,這樣的話會創建大量的類。這時候就能使用裝飾類了。

代碼示例:

抽象構件

public interface AbstractCar {void move(); }

具體構建

public class Car implements AbstractCar{public void move() {System.out.println("路上行駛");} }

裝飾角色

public class SuperCar implements AbstractCar{protected AbstractCar car;public SuperCar(AbstractCar car){this.car=car;}public void move() {car.move();}}

具體裝飾 角色

/*** 飛行汽車 */ ublic class FlyCar extends SuperCar{public FlyCar(AbstractCar car) {super(car);}public void fly() {System.out.println("空中行駛汽車");}@Overridepublic void move() {super.move();fly();}}/*** 水上汽車*/ public class WaterCar extends SuperCar{public WaterCar(AbstractCar car) {super(car);}public void swim() {System.out.println("水上行駛汽車");}@Overridepublic void move() {super.move();swim();}}

客戶端

public class Client {public static void main(String[] args) {Car car=new Car();car.move();System.out.println("------增加新功能,飛行------");FlyCar flyCar=new FlyCar(car);flyCar.move();System.out.println("------新增加功能,水上行駛-----");WaterCar waterCar=new WaterCar(car);waterCar.move();System.out.println("-----新增加兩個功能,飛行與水上行駛-----");WaterCar waterCar2=new WaterCar(flyCar);waterCar2.move();}}//輸出結果 路上行駛 ------增加新功能,飛行------ 路上行駛 空中行駛汽車 ------新增加功能,水上行駛----- 路上行駛 水上行駛汽車 -----新增加兩個功能,飛行與水上行駛----- 路上行駛 空中行駛汽車 水上行駛汽車

2.1.4 另一個很經典的一個場景

  • 咖啡類型 espresso(意大利咖啡),shortblack,LongBlack(美食咖啡),Decaf(無因咖啡)
  • 調料 Milk ,Soy(豆漿),Chocolate
  • 費用 不同的咖啡價格是不同的,而且有 咖啡+調料的類型組合 每個咖啡,都有自己的單價,咖啡+調料也有自己的單價。
  • 要求 擴展咖啡的種類的時候,具有很好的擴展性,改動方便,維護方便。
  • 總結:看到需求,首先是問題的抽象能力,將問題抽象出來,這個抽象能力非常重要。

2.1.5 需求抽象出來

  • 看到每個咖啡,都有自己的cost(花費)和description(描述)可以知道咖啡共有的屬性和行為。
  • 看到問題后,手動畫圖或者用軟件畫出類圖 ,遇到問題,首先是下手,做軟件行業,就是要下手設計,大家都能想到的如下類圖設計
  • 咖啡類型就像是構件,調料就是具體的裝飾類,給構件增加新的功能;

    2.1.6 具體的類圖

    裝飾者模式,更像俄羅斯的套娃,一層一層的嵌套
    看到類圖后你會發現,其實就 當前類A 中 含有A屬性。
    類圖如下:

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zOXHv3mV-1649327214024)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220302211118098.png)]

    代碼: 見idea

    2.1.7 裝飾模式的優點

    • 擴展對象功能,比繼承靈活,不會導致類個數急劇增加。
    • 可以對一個對象進行多次裝飾,創造出不同行為的組合,得到功能更加強大的對象。
    • 具體構 件 類和具體裝飾類可以獨立變化,用戶可以根據需要自己增加新的 具體構件子類和具體裝飾子類。

    2.1.8 缺點

    • 產生很多小對象。大量小的對象占據內存,一定程度上影響性能。
    • 裝飾模式易出錯,調試排查比較麻煩。

    2.2 橋接者模式

    商城中常見的模式 ,以電腦分類,如何處理商品分類銷售問題

    • 我們可以使用多層繼承實現關系如下

      >

    代碼省略: 存在的問題,

    • 擴展問題

    • 如果要增加新的電腦類型:如平板電腦,則要增加 各個品牌下面的類。
    • 如果新增加品牌,也要增加各個電腦下的類。
      • 違反了單一職責原則

      ? 一個類:如聯想筆記本電腦,有兩個引起這個類變化的原因:品牌及電腦的類型。

      總結:某些由于自身的邏輯,它具有兩個或者多個維度的變化,為了應對這種“多維度變化”,并且利用面向對象 的技術來,使得該類能輕松的沿著多個方向變化,而有不引入額外的復雜度。引入bridge模式。

    2.2.1 橋接模式概念

    概念:把抽象(abstraction)和行為實現分開(implement)從而保持各部分的獨立性以及對功能的擴展

    2.2.2 結構圖

    上面場景中有兩個變化的維度,電腦類型和電腦品牌,將上面的代碼通過橋接模式實現:

    2.2.3 具體代碼

    電腦品牌維度

    /*** 電腦品牌維度接口*/ public interface Brand {void nane(); }class Lenovo implements Brand{@Overridepublic void nane() {System.out.println("聯想電腦");} }class Dell implements Brand{@Overridepublic void nane() {System.out.println("戴爾電腦");} }

    電腦類型維度

    /*** 電腦類型維度*/ public class Computer{protected Brand brand;public Computer(Brand brand){this.brand=brand;}public void sale(){brand.nane();} } class Desktop extends Computer{public Desktop(Brand brand) {super(brand);}@Overridepublic void sale() {super.sale();System.out.println("銷售臺式機");} }class Laptop extends Computer{public Laptop(Brand brand) {super(brand);}@Overridepublic void sale() {super.sale();System.out.println("銷售筆記本");}}

    客戶端

    /*** 客戶端*/ public class Client {public static void main(String[] args) {Computer len=new Desktop(new Lenovo());len.sale();} }//輸出結果 聯想電腦 銷售臺式機

    總結:這樣將 電腦品牌和電腦類型兩個維度,分離開并且組合使用,這樣在增加品牌或類型更加簡單。

    2.2.4 橋接模式的設計要點和適用性

    • 設計要點

    處理多層繼承結構,處理多維度變化的場景,將更維度設計成獨立的繼承模塊,使各個維度可以獨立擴展在抽象層。

    • 適用性

    • 如果一個系統需要在構件的抽象化角色和具體化角色之間,增加更多的靈活性,避免在兩個層次之間建立靜態的關系。
    • 設計要求實現化角色的任何改變不應該影響客戶端,或者說實現化角色的改變對客戶端是完全透明的。
    • 一個構件多余一個抽象化角色和實現化角色,系統需要它們之間互相解耦。
    • 雖然系統中使用繼承沒有問題,但由于抽象化角色和具體化角色需要獨立化,設計要求獨立管理兩者。

    2.2.5 裝飾模式和橋接模式的區別

    • 兩個模式都是為了解決過多子類對象的問題。但他們的誘因不同,橋接模式是對象自身現有機制沿著多個維度變化,是既有部分不穩定。裝飾模式是為了增加新的功能

    2.3 觀察者模式

    場景: 是一種 一對多的關系,進一步理解為 消息訂閱模式

    Subject 被觀察者 也叫做 主題 Observer 觀察者 也叫訂閱者 理解:被觀察者 通知觀察者自己的狀態變化 被觀察者中注冊了,多個觀察者對象。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rPyA2BFY-1649327214026)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220302213558321.png)]

    2.4 責任鏈模式

    2.5 建造者模式

    2.5.1 概念

    將復雜對象的構建和它的表示,使得同樣的構建過程有不同的創建方式。

    2.6 組合這模式

    2.6.1 組合模式的概念

    概念 把部分和整體用樹形結構來表示 ,從而使客戶端可以使用統一的方式對,部分對象和整體對象就行管理。

    2.6.2 組合模式結構

    抽象構件(Conponent) 角色: 所有類共有接口,定義葉子節點和容器共同點

    葉子(Leaf)構件角色:在組合中表示葉子節點對象,葉子節點五子節點。

    容器(Composite)構件角色: 有容器特征,可以用來存儲子節點,在Component接口中實現與子節點有關操作,如增加(add)和刪除(remove)等。

    2.6.3組合模式工作分析

    • 組合模式為處理樹形結構,提供了完美的解決方案,描述了如何將容器和葉子節點進行遞歸組合,使得用戶在使用時, 可以一致性的對待容器和葉子。
    • 當容器對象的指定方法被調用時,將遍歷整個樹形結構,尋找包含這個方法的成員,并調用執行。其中使用遞歸調用機制對整個機構進行處理。

    下面是通過簡單秒殺的例子,使用組合

    抽象構建

    public interface AbstractFile {void killVirus();//殺毒 }

    葉子構件

    class ImageFile implements AbstractFile{private String name;public ImageFile(String name){this.name=name;}public void killVirus() {System.out.println("---對圖像文件"+name+"殺毒");}} class TextFile implements AbstractFile{private String name;public TextFile(String name){this.name=name;}public void killVirus() {System.out.println("---對文本文件"+name+"殺毒");}}

    容器構建

    class Folder implements AbstractFile{private String name;private ArrayList<AbstractFile> list=new ArrayList<AbstractFile>();public Folder(String name){this.name=name;}public void add(AbstractFile file){list.add(file);}public void remove(AbstractFile file){list.remove(file);}public AbstractFile getChild(int index){return list.get(index);}public void killVirus() {System.out.println("---對文件夾"+name+"殺毒");for(AbstractFile file:list){file.killVirus();}}}

    客戶端

    public class Client {public static void main(String[] args) {Folder f1;AbstractFile f2,f3;f1=new Folder("我的收藏");f2=new ImageFile("my.jpg");f3=new TextFile("my.txt");f1.add(f2);f1.add(f3);f1.killVirus();}}//輸出結果: ---對文件夾我的收藏殺毒 ---對圖像文件my.jpg殺毒 ---對文本文件my.txt殺毒

    2.7 策略模式

    組合關系

    2.8 外觀模式

    2.8.1 概念

    • 外觀模式(也稱門面模式)定義了一個高層接口,為子系統中的一組接口提供了,一致的界面,從而使子系統更加容易使用。

    2.9 命令模式

    2.9.1 概念

    將一個請求封裝為對象,從而使我們可用不同的請求,對客戶進行參數化;對請求排隊或者記錄請求日志,以及支持撤銷操作,以及支持撤銷操作。也稱為:動作(Action)模式,事務(transaction)模式。

    2.9.2 模式結構

    • Conmmand 抽象命令類: 聲明執行操作接口

    • ConcreteCommand 具體命令類:通常持有 一個接收者對象并綁定一個動作,調用接收者相應的動作,以實現execute方法。

    • invoker 調用者/請求者:請求的發送者,它通過命令對象來執行請求。一個調用者并不需要在設計時確定其接收者,因此它只與抽象命令類之間存在關聯。在程序運行時,將調用命令對象的execute() 間接調用接收者的相關工作。

    • Receiver接收者:接受者執行與請求相關的操作,具體實現對請求業務的處理。

    2.9.3 結構圖

    Receiver接受者

    /*** 真正的命令執行者*/ public class Receiver {public void action(){System.out.println("執行命令----");}public void unAction(){System.out.println("撤銷命令----");}}

    command 抽象命令類

    /*** 抽象命令接口*/ public interface Command {void execute();//執行命令void cancel();//取消命令 }

    ConcreteCommand具體命令類

    /*** 具體命令類*/ public class ConcreteCommand implements Command{private Receiver receiver;public ConcreteCommand(Receiver receiver) {super();this.receiver = receiver;}public void execute() {//可進行執行命令前相關操作receiver.action();//執行命令//可進行執行命令后相關操作}public void cancel() {receiver.unAction();} }

    Invoke 調用者/請求者

    public class Invoker {private Command command; //可以是多個命令public Invoker(Command command) {super();this.command = command;}//執行命令public void runCommand(){command.execute();}//取消命令public void cancelCommand(){command.cancel();}}

    客戶端

    public class Client {public static void main(String[] args) {//創建接收者Receiver receiver=new Receiver();//創建命令對象,并設置接收者Command command=new ConcreteCommand(receiver);//創建調用者,設置命令Invoker invoker=new Invoker(command);invoker.runCommand();invoker.cancelCommand();} }//輸出結果 執行命令---- 撤銷命令----

    2.9.3建議看這個代碼

    應用 :模擬對電視機的操作有開機、關機、換臺命令。代碼如下

    //執行命令的接口 public interface Command {void execute(); } //命令接收者Receiver public class Tv {public int currentChannel = 0;public void turnOn() {System.out.println("The televisino is on.");}public void turnOff() {System.out.println("The television is off.");}public void changeChannel(int channel) {this.currentChannel = channel;System.out.println("Now TV channel is " + channel);} } //開機命令ConcreteCommand public class CommandOn implements Command {private Tv myTv;public CommandOn(Tv tv) {myTv = tv;}public void execute() {myTv.turnOn();} } //關機命令ConcreteCommand public class CommandOff implements Command {private Tv myTv;public CommandOff(Tv tv) {myTv = tv;}public void execute() {myTv.turnOff();} } //頻道切換命令ConcreteCommand public class CommandChange implements Command {private Tv myTv;private int channel;public CommandChange(Tv tv, int channel) {myTv = tv;this.channel = channel;}public void execute() {myTv.changeChannel(channel);} } //可以看作是遙控器Invoker public class Control {private Command onCommand, offCommand, changeChannel;public Control(Command on, Command off, Command channel) {onCommand = on;offCommand = off;changeChannel = channel;}public void turnOn() {onCommand.execute();}public void turnOff() {offCommand.execute();}public void changeChannel() {changeChannel.execute();} } //測試類Client public class Client {public static void main(String[] args) {// 命令接收者ReceiverTv myTv = new Tv();// 開機命令ConcreteCommondCommandOn on = new CommandOn(myTv);// 關機命令ConcreteCommondCommandOff off = new CommandOff(myTv);// 頻道切換命令ConcreteCommondCommandChange channel = new CommandChange(myTv, 2);// 命令控制對象InvokerControl control = new Control(on, off, channel);// 開機control.turnOn();// 切換頻道control.changeChannel();// 關機control.turnOff();} }

    執行結果

    The televisino is on. Now TV channel is 2 The television is off.

    2.9.4 命令模式的優缺點

    • 優點
  • 降低對象的耦合度。
  • 新的命令很容易加入到系統中。
  • 可以很容易的設計一套命令。
  • 調用同一個方法不同功能
    • 缺點
  • 使用命令模式可能會導致某些系統有很多具體的命令類,因為針對每一個命令需要設計一個命令類,因此某些系統可能需要大量的命令類,將影響命令模式的使用。
    • 總結

    • 命令模式本質是對,命令進行封裝,將發出命令的責任和執行命令的責任分割開。
    • 每一個命令都是一個操作,請求一方發出命令,要求執行一個動作;接收方收到請求,并執行請求。
    • 命令模式允許請求的一方和接收的一方,獨立開來,使得請求方不知道接收方的接口,更不知道請求是怎么被接收,以及是否被執行,何時被執行,以及怎么被執行。
    • 命令模式使請求本身成為對象,這個對象和其他對象可以被存儲和傳遞。
    • 命令模式的關鍵在于引入抽象接口,且發送者針對抽象接口編程,只有實現了抽象命令接口的具體命令才能與接收者相關聯。

    總結

    以上是生活随笔為你收集整理的java后端分享整理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。