一文徹底了解Java的組合模式
相信樹(shù)形結(jié)構(gòu)大家都知道,但是你是否知道用到了什么設(shè)計(jì)模式嗎?
1、什么是組合模式
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
組合模式(Composite Pattern):將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu), 使得用戶(hù)對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
說(shuō)人話:用于處理樹(shù)形結(jié)構(gòu)數(shù)據(jù)。
2、組合模式定義
①、Component 抽象構(gòu)件角色
定義參加組合對(duì)象的共有方法和屬性,可以定義一些默認(rèn)的行為或?qū)傩浴?/p>
②、Leaf 葉子節(jié)點(diǎn)
葉子對(duì)象,其下再也沒(méi)有其他的子節(jié)點(diǎn),是遍歷的最小單位。
③、Composite 樹(shù)枝構(gòu)件
樹(shù)枝對(duì)象,作用是組合樹(shù)枝節(jié)點(diǎn)和葉子節(jié)點(diǎn)形成一個(gè)樹(shù)形結(jié)構(gòu)。
3、組合模式通用代碼實(shí)現(xiàn)
/** * 個(gè)體和整體的抽象 */ public abstract class Component { // 個(gè)體和整體都有的共享 public void doSomething(){ // 通用業(yè)務(wù)邏輯 System.out.println("通用業(yè)務(wù)邏輯"); }
/** * 樹(shù)枝節(jié)點(diǎn) */ public class Composite extends Component{ // 構(gòu)件容器 private ArrayList<Component> componentArrayList = new ArrayList<>(); // 增加一個(gè)葉子節(jié)點(diǎn)或者樹(shù)枝節(jié)點(diǎn) public void add(Component component){ this.componentArrayList.add(component); } // 刪除一個(gè)葉子節(jié)點(diǎn)或者樹(shù)枝節(jié)點(diǎn) public void remove(Component component){ this.componentArrayList.remove(component); } // 獲取分支下所有葉子節(jié)點(diǎn)和樹(shù)枝節(jié)點(diǎn) public List<Component> getChildren(){ return this.componentArrayList; } }
/** * 葉子節(jié)點(diǎn) */ public class Leaf extends Component { // 覆寫(xiě)父類(lèi)方法 @Override public void doSomething() { // 葉子節(jié)點(diǎn)邏輯 System.out.println("葉子節(jié)點(diǎn)邏輯"); } }
測(cè)試:
public class ClientTest { public static void main(String[] args) { // 創(chuàng)建一個(gè)根節(jié)點(diǎn) Composite root = new Composite(); root.doSomething(); // 創(chuàng)建一個(gè)樹(shù)枝構(gòu)件 Composite branch = new Composite(); // 創(chuàng)建一個(gè)葉子節(jié)點(diǎn) Leaf leaf = new Leaf(); // 串聯(lián)起來(lái) root.add(branch); branch.add(leaf); display(root); } // 通過(guò)遞歸遍歷數(shù) public static void display(Composite root){ for(Component c : root.getChildren()){ if(c instanceof Leaf){ // 葉子節(jié)點(diǎn) c.doSomething(); }else{ display((Composite) c); } } } }
這里我們?cè)谂e一個(gè)例子:
假設(shè)我們?cè)陂_(kāi)發(fā)一個(gè) OA 系統(tǒng)(辦公自動(dòng)化系統(tǒng))。公司的組織結(jié)構(gòu)包含部門(mén)和員工兩種數(shù)據(jù)類(lèi)型。其中,部門(mén)又可以包含子部門(mén)和員工。
我們希望在內(nèi)存中構(gòu)建整個(gè)公司的人員架構(gòu)圖(部門(mén)、子部門(mén)、員工的隸屬關(guān)系),并且提供接口計(jì)算出部門(mén)的薪資成本(隸屬于這個(gè)部門(mén)的所有員工的薪資和)。
/** * 部門(mén)類(lèi)和員工類(lèi)的抽象類(lèi) */ 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<HumanResource> 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; } }
測(cè)試:
public class PersonClientTest { private static final long ORGANIZATION_ROOT_ID = 1; public static void main(String[] args) { // 創(chuàng)建總部門(mén) Department root = new Department(ORGANIZATION_ROOT_ID); // 創(chuàng)建子部門(mén) 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ù) 部門(mén)id 查詢(xún)數(shù)據(jù)庫(kù) 所有下屬部門(mén) id // List<Long> subDepartmentIds = departmentRepo.getSubDepartmentIds(department.getId()); List<Long> subDepartmentIds = new ArrayList<>(); for (Long subDepartmentId : subDepartmentIds){ Department subDepartment = new Department(subDepartmentId); department.addSubNode(subDepartment); buildOrganization(subDepartment); } // 根據(jù)部門(mén)id 查詢(xún)數(shù)據(jù)庫(kù) 其關(guān)聯(lián)員工所有 id // List<Long> employeeIds = employeeRepo.getDepartmentEmployeeIds(department.getId()); List<Long> employeeIds = new ArrayList<>(); for (Long employeeId : employeeIds){ // 根據(jù) employeeId 查詢(xún)數(shù)據(jù)庫(kù)得到 salary // 假設(shè)為 1000 double salary = 1000d; department.addSubNode(new Employee(employeeId,salary)); } } }
4、組合模式優(yōu)點(diǎn)
①、高層模塊調(diào)用簡(jiǎn)單
一棵樹(shù)形機(jī)構(gòu)中的所有節(jié)點(diǎn)都是Component, 局部和整體對(duì)調(diào)用者來(lái)說(shuō)沒(méi)有任何區(qū)別,也就是說(shuō), 高層模塊不必關(guān)心自己處理的是單個(gè)對(duì)象還是整個(gè)組合結(jié)構(gòu), 簡(jiǎn)化了高層模塊的代碼。
②、節(jié)點(diǎn)自由增加
使用了組合模式后, 如果想增加一個(gè)樹(shù)枝節(jié)點(diǎn)、 葉子節(jié)點(diǎn)都很容易, 只要找到它的父節(jié)點(diǎn)就成, 非常容易擴(kuò)展, 符合開(kāi)閉原則, 對(duì)以后的維護(hù)非常有利。
5、組合模式應(yīng)用場(chǎng)景
只要是樹(shù)形結(jié)構(gòu),就可以考慮使用組合模式。
①、維護(hù)和展示部分-整體關(guān)系的場(chǎng)景, 如樹(shù)形菜單、 文件和文件夾管理。
②、從一個(gè)整體中能夠獨(dú)立出部分模塊或功能的場(chǎng)景。
到此這篇關(guān)于一文徹底了解Java的組合模式的文章就介紹到這了,更多相關(guān)Java組合模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)6種字符串?dāng)?shù)組的排序(String array sort)
這篇文章主要介紹了java實(shí)現(xiàn)6種字符串?dāng)?shù)組的排序(String array sort),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01spring data jpa 查詢(xún)自定義字段,轉(zhuǎn)換為自定義實(shí)體方式
這篇文章主要介紹了spring data jpa 查詢(xún)自定義字段,轉(zhuǎn)換為自定義實(shí)體方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06關(guān)于Hibernate的一些學(xué)習(xí)心得總結(jié)
Hibernate是一個(gè)優(yōu)秀的Java 持久化層解決方案,是當(dāng)今主流的對(duì)象—關(guān)系映射(ORM)工具2013-07-07Java 9中如何對(duì)IntegerCache進(jìn)行修改詳解
這篇文章主要給大家介紹了關(guān)于Java 9中如何對(duì)IntegerCache進(jìn)行修改的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或使用java9具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。2017-12-12mybatis-plus QueryWrapper and or 連用并且實(shí)現(xiàn)分
這篇文章主要介紹了mybatis-plus QueryWrapper and or 連用并且實(shí)現(xiàn)分頁(yè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01spring配置文件中util:properties和context:property-placeholder用法
這篇文章主要介紹了spring配置文件中util:properties和context:property-placeholder用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01