<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          設(shè)計模式之組合模式

          共 4827字,需瀏覽 10分鐘

           ·

          2021-11-22 16:00

          設(shè)計模式專欄

          ?

          1、什么是組合模式?

          Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.

          組合模式(Composite Pattern):將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu), 使得用戶對單個對象和組合對象的使用具有一致性。

          說人話:用于處理樹形結(jié)構(gòu)數(shù)據(jù)。

          2、組合模式定義

          6666f4db6a68fe3b43bc5565417a8ee0.webp

          ①、Component 抽象構(gòu)件角色

          定義參加組合對象的共有方法和屬性,可以定義一些默認的行為或?qū)傩浴?/p>

          ②、Leaf 葉子節(jié)點

          葉子對象,其下再也沒有其他的子節(jié)點,是遍歷的最小單位。

          ③、Composite 樹枝構(gòu)件

          樹枝對象,作用是組合樹枝節(jié)點和葉子節(jié)點形成一個樹形結(jié)構(gòu)。

          3、組合模式通用代碼實現(xiàn)

          /**
          ?*?個體和整體的抽象
          ?*/

          public?abstract?class?Component?{
          ????//?個體和整體都有的共享
          ????public?void?doSomething(){
          ????????//?通用業(yè)務(wù)邏輯
          ????????System.out.println("通用業(yè)務(wù)邏輯");
          ????}
          }
          /**
          ?*?樹枝節(jié)點
          ?*/

          public?class?Composite?extends?Component{
          ????//?構(gòu)件容器
          ????private?ArrayList?componentArrayList?=?new?ArrayList<>();

          ????//?增加一個葉子節(jié)點或者樹枝節(jié)點
          ????public?void?add(Component?component){
          ????????this.componentArrayList.add(component);
          ????}

          ????//?刪除一個葉子節(jié)點或者樹枝節(jié)點
          ????public?void?remove(Component?component){
          ????????this.componentArrayList.remove(component);
          ????}

          ????//?獲取分支下所有葉子節(jié)點和樹枝節(jié)點
          ????public?List?getChildren(){
          ????????return?this.componentArrayList;
          ????}
          }
          /**
          ?*?葉子節(jié)點
          ?*/

          public?class?Leaf?extends?Component?{

          ????//?覆寫父類方法
          ????@Override
          ????public?void?doSomething()?{
          ????????//?葉子節(jié)點邏輯
          ????????System.out.println("葉子節(jié)點邏輯");
          ????}
          }

          測試:

          public?class?ClientTest?{

          ????public?static?void?main(String[]?args)?{
          ????????//?創(chuàng)建一個根節(jié)點
          ????????Composite?root?=?new?Composite();
          ????????root.doSomething();
          ????????//?創(chuàng)建一個樹枝構(gòu)件
          ????????Composite?branch?=?new?Composite();
          ????????//?創(chuàng)建一個葉子節(jié)點
          ????????Leaf?leaf?=?new?Leaf();

          ????????//?串聯(lián)起來
          ????????root.add(branch);
          ????????branch.add(leaf);

          ????????display(root);
          ????}

          ????//?通過遞歸遍歷數(shù)
          ????public?static?void?display(Composite?root){
          ????????for(Component?c?:?root.getChildren()){
          ????????????if(c?instanceof?Leaf){?//?葉子節(jié)點
          ????????????????c.doSomething();
          ????????????}else{
          ????????????????display((Composite)?c);
          ????????????}
          ????????}
          ????}
          }

          這里我們在舉一個例子:

          假設(shè)我們在開發(fā)一個 OA 系統(tǒng)(辦公自動化系統(tǒng))。公司的組織結(jié)構(gòu)包含部門和員工兩種數(shù)據(jù)類型。其中,部門又可以包含子部門和員工。

          我們希望在內(nèi)存中構(gòu)建整個公司的人員架構(gòu)圖(部門、子部門、員工的隸屬關(guān)系),并且提供接口計算出部門的薪資成本(隸屬于這個部門的所有員工的薪資和)。

          51610915d316dae434d066a319f0a576.webp


          /**
          ?*?部門類和員工類的抽象類
          ?*/

          public?abstract?class?HumanResource?{
          ????protected?long?id;
          ????protected?double?salary;

          ????public?HumanResource(long?id){
          ????????this.id?=?id;
          ????}

          ????public?long?getId(){
          ????????return?id;
          ????}

          ????public?abstract?double?calculateSalary();

          }
          public?class?Department?extends?HumanResource{
          ????private?List?subNodes?=?new?ArrayList<>();

          ????public?Department(long?id){
          ????????super(id);
          ????}

          ????@Override
          ????public?double?calculateSalary()?{
          ????????double?totalSalary?=?0d;
          ????????for?(HumanResource?hr?:?subNodes){
          ????????????totalSalary?+=?hr.calculateSalary();
          ????????}
          ????????this.salary?=?totalSalary;
          ????????return?totalSalary;
          ????}

          ????public?void?addSubNode(HumanResource?humanResource){
          ????????subNodes.add(humanResource);
          ????}
          }
          public?class?Employee?extends?HumanResource{
          ????public?Employee(long?id,double?salary){
          ????????super(id);
          ????????this.salary?=?salary;
          ????}

          ????@Override
          ????public?double?calculateSalary()?{
          ????????return?salary;
          ????}
          }

          測試:

          public?class?PersonClientTest?{
          ????private?static?final?long?ORGANIZATION_ROOT_ID?=?1;

          ????public?static?void?main(String[]?args)?{
          ????????//?創(chuàng)建總部門
          ????????Department?root?=?new?Department(ORGANIZATION_ROOT_ID);

          ????????//?創(chuàng)建子部門
          ????????Department?branch?=?new?Department(2L);

          ????????//?創(chuàng)建員工
          ????????Employee?employee1?=?new?Employee(21L,2000);
          ????????Employee?employee2?=?new?Employee(22L,4000);

          ????????root.addSubNode(branch);
          ????????branch.addSubNode(employee1);
          ????????branch.addSubNode(employee2);

          ????????double?v?=?root.calculateSalary();
          ????????System.out.println(v);
          ????}

          ????private?void?buildOrganization(Department?department){
          ????????//?根據(jù)?部門id?查詢數(shù)據(jù)庫?所有下屬部門?id
          ????????//?List?subDepartmentIds?=?departmentRepo.getSubDepartmentIds(department.getId());
          ????????List?subDepartmentIds?=?new?ArrayList<>();

          ????????for?(Long?subDepartmentId?:?subDepartmentIds){
          ????????????Department?subDepartment?=?new?Department(subDepartmentId);
          ????????????department.addSubNode(subDepartment);
          ????????????buildOrganization(subDepartment);
          ????????}

          ????????//?根據(jù)部門id?查詢數(shù)據(jù)庫?其關(guān)聯(lián)員工所有?id
          ????????//?List?employeeIds?=?employeeRepo.getDepartmentEmployeeIds(department.getId());
          ????????List?employeeIds?=?new?ArrayList<>();
          ????????for?(Long?employeeId?:?employeeIds){
          ????????????//?根據(jù)?employeeId?查詢數(shù)據(jù)庫得到?salary
          ????????????//?假設(shè)為?1000
          ????????????double?salary?=?1000d;
          ????????????department.addSubNode(new?Employee(employeeId,salary));
          ????????}


          ????}
          }

          4、組合模式優(yōu)點

          ①、高層模塊調(diào)用簡單

          一棵樹形機構(gòu)中的所有節(jié)點都是Component, 局部和整體對調(diào)用者來說沒有任何區(qū)別,也就是說, 高層模塊不必關(guān)心自己處理的是單個對象還是整個組合結(jié)構(gòu), 簡化了高層模塊的代碼。

          ②、節(jié)點自由增加

          使用了組合模式后, ?如果想增加一個樹枝節(jié)點、 葉子節(jié)點都很容易, 只要找到它的父節(jié)點就成, 非常容易擴展, 符合開閉原則, 對以后的維護非常有利。

          5、組合模式應用場景

          只要是樹形結(jié)構(gòu),就可以考慮使用組合模式。

          ①、維護和展示部分-整體關(guān)系的場景, 如樹形菜單、 文件和文件夾管理。

          ②、從一個整體中能夠獨立出部分模塊或功能的場景


          關(guān)于我

          可樂是一個熱愛技術(shù)的Java程序猿,公眾號「IT可樂」定期分享有趣有料的精品原創(chuàng)文章!

          b13b2f6c784928c57a53958b615ea113.webp

          非常感謝各位人才能看到這里,原創(chuàng)不易,文章如果有幫助可以關(guān)注、點贊、分享或評論,這都是對我的莫大支持!

          愿你我人生盡量沒有遺憾的事,愿你我都能奔赴在各自想去的路上。

          瀏覽 70
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月深深爱亭亭 | 色天使亚洲 | 天堂在线日韩 | 天天插天天插 | 久色视频在线 |