一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解

設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解

2020-09-21 14:19雙子孤狼 Java教程

這篇文章主要介紹了組合模式及其在JDK和MyBatis源碼中的運用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

組合模式及其在JDK源碼中的運用 前言組合和聚合什么是組合模式示例透明組合模式透明組合模式的缺陷安全組合模式 組合模式角色組合模式在JDK源碼中的體現組合模式應用場景享元模式優缺點總結

前言

本文主要會講述組合模式的用法,并會結合在JDK和MyBatis源碼中的運用來進一步理解組合模式。

在編碼原則中,有一條是:多用組合,少用繼承。當然這里的組合和我們今天要講的組合模式并不等價,這里的組合其實就是一種聚合,那么聚合和組合有什么區別呢?

組合和聚合

人在一起叫團伙,心在一起叫團隊。用這句話來詮釋組合與聚合的區別是相對恰當的。

聚合就是說各個對象聚合在一起工作,但是我沒有你也行,我照樣可以正常運行。但是組合呢,關系就比較密切,組合中的各個對象之間組成了一個整體,缺少了某一個對象就不能正常運行或者說功能會有很大缺陷。
也就是說聚合對象不具備相同生命周期,而組合的對象具有相同的生命周期

舉個例子:
比如說電腦和U盤就是聚合,而電腦顯示器和主機就是組合。

什么是組合模式

組合模式(Composite Pattern)也稱之為整體-部分(Part-Whole)模式。組合模式的核心是通過將單個對象(葉子節點)和組合對象(樹枝節點)用相同的接口進行表示,使得單個對象和組合對象的使用具有一致性。組合模式屬于結構型模式。

組合模式一般用來描述整體與部分的關系,它將對象組織到樹形結構中,最頂層的節點稱為根節點,根節點下面可以包含樹枝節點和葉子節點,樹枝節點下面又可以包含樹枝節點和葉子節點如下圖所示:

設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解

講了這么多,感覺有點抽象,所以依然是老規矩:Talk is cheap,Show you the code。

示例

組合模式有兩種寫法,分別是透明模式安全模式。下面我們就以高考的科目為例來看看組合模式是如何體現在代碼中的

透明組合模式

1、首先建立一個頂層的抽象科目類,這個類中定義了三個通用操作方法,但是均默認不支持操作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.zwx.design.pattern.composite.transparency;
 
/**
 * 頂層抽象組件
 */
public abstract class GkAbstractCourse {
  public void addChild(GkAbstractCourse course){
    System.out.println("不支持添加操作");
  }
 
  public String getName() throws Exception {
    throw new Exception("不支持獲取名稱");
  }
 
  public void info() throws Exception{
    throw new Exception("不支持查詢信息操作");
  }
}

PS:這個類中的公共方法之所以不定義為抽象方法的原因是因為假如定義為抽象方法,那么所有的子類都必須重寫父類方法,這樣體現不出差異性。而這種通過拋異常的方式,如果子類需要用到的功能就重寫覆蓋父類方法即可。

2、新建一個普通科目類繼承通用科目抽象類,這個類作為葉子節點,沒有重寫addChild方法,也就是這個類屬于葉子節點,不支持添加子節點:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.zwx.design.pattern.composite.transparency;
 
/**
 * 普通科目類(葉子節點)
 */
public class CommonCource extends GkAbstractCourse {
  private String name;//課程名稱
  private String score;//課程分數
 
  public CommonCource(String name, String score) {
    this.name = name;
    this.score = score;
  }
 
  @Override
  public String getName(){
    return this.name;
  }
 
  @Override
  public void info() {
    System.out.println("課程:" + this.name + ",分數:" + score);
  }
}

3、建立一個具有層級的節點,三個方法都重寫了,支持添加子節點,這個類里面為了方便打印的時候看出層級關系,所以我定義了一個層級屬性。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.zwx.design.pattern.composite.transparency;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * 樹枝節點
 */
public class LevelCource extends GkAbstractCourse{
  private List<GkAbstractCourse> courseList = new ArrayList<>();
  private String name;
  private int level;
 
  public LevelCource(String name, int level) {
    this.name = name;
    this.level = level;
  }
 
  @Override
  public void addChild(GkAbstractCourse course) {
    courseList.add(course);
  }
 
  @Override
  public String getName(){
    return this.name;
  }
 
  @Override
  public void info() throws Exception {
    System.out.println("課程:" + this.name);
    for (GkAbstractCourse course : courseList){
      for (int i=0;i<level;i++){
        System.out.print(" ");
      }
      System.out.print(">");
      course.info();
    }
  }
}

4、建立一個測試類來測試一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.zwx.design.pattern.composite.transparency;
 
public class TestTransparency {
  public static void main(String[] args) throws Exception {
    GkAbstractCourse ywCourse = new CommonCource("語文","150");
    GkAbstractCourse sxCourse = new CommonCource("數學","150");
    GkAbstractCourse yyCourse = new CommonCource("英語","150");
 
    GkAbstractCourse wlCourse = new CommonCource("物理","110");
    GkAbstractCourse hxCourse = new CommonCource("化學","100");
    GkAbstractCourse swCourse = new CommonCource("生物","90");
 
    GkAbstractCourse lzCourse = new LevelCource("理綜",2);
    lzCourse.addChild(wlCourse);
    lzCourse.addChild(hxCourse);
    lzCourse.addChild(swCourse);
 
    GkAbstractCourse gkCourse = new LevelCource("理科高考科目",1);
    gkCourse.addChild(ywCourse);
    gkCourse.addChild(sxCourse);
    gkCourse.addChild(yyCourse);
    gkCourse.addChild(lzCourse);
    
    gkCourse.info();
  }
}

輸出結果:

課程:理科高考科目
  >課程:語文,分數:150
  >課程:數學,分數:150
  >課程:英語,分數:150
  >課程:理綜
    >課程:物理,分數:110
    >課程:化學,分數:100
    >課程:生物,分數:90

這里如果用普通科目去調用add方法就會拋出異常,假如上面調用:

?
1
swCourse.addChild(ywCourse);

會輸出

不支持添加操作

因為在普通科目類里面并沒有重寫addChild方法。

透明組合模式的缺陷

透明模式的特點就是將組合對象所有的公共方法都定義在了抽象組件內,這樣做的好處是客戶端無需分辨當前對象是屬于樹枝節點還是葉子節點,因為它們具備了完全一致的接口,不過缺點就是葉子節點得到到了一些不屬于它的方法,比如上面的addChild方法,這違背了接口隔離性原則

安全組合模式

安全組合模式只是規定了系統各個層次的最基礎的一致性行為,而把組合(樹節點)本身的方法(如樹枝節點管理子類的addChild等方法)放到自身當中。

1、首先還是建立一個頂層的抽象根節點(這里面只定義了一個通用的抽象info方法):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.zwx.design.pattern.composite.safe;
 
package com.zwx.design.pattern.composite.safe;
 
/**
 * 頂層抽象組件
 */
public abstract class GkAbstractCourse {
  protected String name;
  protected String score;
 
  public GkAbstractCourse(String name, String score) {
    this.name = name;
    this.score = score;
  }
 
  public abstract void info();
}

2、建立一個葉子節點(這里只是重寫了info方法,沒有定義其他特有方法):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.zwx.design.pattern.composite.safe;
 
/**
 * 葉子節點
 */
public class CommonCource extends GkAbstractCourse {
 
  public CommonCource(String name,String score) {
    super(name,score);
  }
 
  @Override
  public void info() {
    System.out.println("課程:" + this.name + ",分數:" + this.score);
  }
}

3、定義一個樹枝節點(這個類當中定義了一個樹枝特有的方法addChild):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.zwx.design.pattern.composite.safe;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * 樹枝節點
 */
public class LevelCource extends GkAbstractCourse{
  private List<GkAbstractCourse> courseList = new ArrayList<>();
  private int level;
 
  public LevelCource(String name, String score,int level) {
    super(name,score);
    this.level = level;
  }
 
  public void addChild(GkAbstractCourse course) {
    courseList.add(course);
  }
 
  @Override
  public void info() {
    System.out.println("課程:" + this.name + ",分數:" + this.score);
    for (GkAbstractCourse course : courseList){
      for (int i=0;i<level;i++){
        System.out.print(" ");
      }
      System.out.print(">");
      course.info();
    }
  }
}

4、新建測試類來測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.zwx.design.pattern.composite.safe;
 
public class TestSafe {
  public static void main(String[] args) throws Exception {
    CommonCource ywCourse = new CommonCource("語文","150");
    CommonCource sxCourse = new CommonCource("數學","150");
    CommonCource yyCourse = new CommonCource("英語","150");
 
    CommonCource wlCourse = new CommonCource("物理","110");
    CommonCource hxCourse = new CommonCource("化學","100");
    CommonCource swCourse = new CommonCource("生物","90");
 
    LevelCource lzCourse = new LevelCource("理綜","300",2);
    lzCourse.addChild(wlCourse);
    lzCourse.addChild(hxCourse);
    lzCourse.addChild(swCourse);
 
    LevelCource gkCourse = new LevelCource("理科高考","750",1);
    gkCourse.addChild(ywCourse);
    gkCourse.addChild(sxCourse);
    gkCourse.addChild(yyCourse);
 
    gkCourse.addChild(lzCourse);
    gkCourse.info();
  }
}

輸出結果為:

課程:理科高考,分數:750
  >課程:語文,分數:150
  >課程:數學,分數:150
  >課程:英語,分數:150
  >課程:理綜,分數:300
    >課程:物理,分數:110
    >課程:化學,分數:100
    >課程:生物,分數:90

這里和透明方式不一樣,葉子節點不具備addChild功能,所以無法調用,而上面的示例中時可以被調用,但是調用之后顯示不支持,這就是這兩種寫法最大的區別。

組合模式角色

從上面示例中,可以看到組合模式包含了以下三個角色:

  • 抽象根節點(Component):定義系統各層次對象的公有屬性和方法,可以預先定義一些默認行為和屬性。
  • 樹枝節點(Composite):定義樹枝節點的行為,存儲子節點,組合樹枝節點和葉子節點形成一個樹形結構。
  • 葉子節點(Leaf):是系統遍歷層次中的最小單位,下面沒有子節點。

組合模式在JDK源碼中的體現

1、HashMap

HashMap中有一個putAll方法,參數是一個Map,這就是一種組合模式的體現:

設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解

另外還有ArrayList中的addAll方法也是一樣。

2、MyBatis中有一個SqlNode接口,下面很多一級標簽:

設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解

然后一級標簽下面又有二級標簽(這就是組合模式的體現):

設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解

組合模式應用場景

組合模式一般應用在有層級關系的場景,最經典的就是樹形菜單,文件和文件夾的管理等

享元模式優缺點

優點:清楚的定義了分層次的復雜對象,讓客戶端可以忽略層次的差異,方便對整個層次進行動態控制。
缺點:其葉子和樹枝的聲明是實現類而不是接口,違反了依賴倒置原則,而且組合模式會使設計更加抽象不好理解。

總結

本文主要介紹了組合模式,并介紹了普通的聚合和組合之間的區別,并通過例子詳細解釋了組合模式中的透明寫法和安全寫法的區別,最后結合在JDK和MyBatis源碼中的運用來進一步理解組合模式的運用。
請關注我,和孤狼一起學習進步

到此這篇關于設計模式系列之組合模式及其在JDK和MyBatis源碼中的運用詳解的文章就介紹到這了,更多相關組合模式在JDK和MyBatis源碼中的運用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/zwx900102/article/details/108554255

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 91精品91 | 法国贵妇一级伦理hd | 夫妻性生活在线 | 亚洲 日韩 在线 国产 视频 | 日韩一级片在线观看 | 欧美粗黑巨大gay | 高黄h文各种play| xxxx18日本视频xxxxx | 国产精品久久久久影院色老大 | dasd817黑人在线播放 | 污文啊好棒棒啊好了 | 久久99re8热在线播放 | 楚乔传第二部全60集免费观看 | 操动漫美女视频 | 久久re视频这里精品一本到99 | 国产精品香蕉在线观看不卡 | 女人pp被扒开流水了 | 嫩草在线观看视频 | jizzjizzjⅰzz亚洲美女 | 国产精品久久久久久久久齐齐 | 操美女b| 亚洲 欧美 日韩 综合 | 欧美添下面视频免费观看 | 欧美日韩精品一区二区三区视频在线 | 色婷婷综合久久久中文字幕 | 国内精品91最新在线观看 | 第一次做m被调教经历 | 欧美大b | 日本在线小视频 | 美女岳肉太深了使劲 | 1024毛片 | 亚洲男gay同性同志 亚洲免费在线看 | 亚洲AV无码乱码在线观看浪潮 | 99热这里只有精品在线观看 | 日本在线观看免费高清 | 亚洲成人99 | 亚洲精品九色在线网站 | 青青草成人在线 | 欧美人禽杂交狂配无删完整 | 日本高清无吗 | 日韩在线资源 |