相信樹形結構大家都知道,但是是否知道用到了什么設計模式嗎?
1、什么是組合模式?
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
組合模式(Composite Pattern):將對象組合成樹形結構以表示“部分-整體”的層次結構, 使得用戶對單個對象和組合對象的使用具有一致性。
說人話:用于處理樹形結構數據。
2、組合模式定義
①、Component 抽象構件角色
定義參加組合對象的共有方法和屬性,可以定義一些默認的行為或屬性。
②、Leaf 葉子節點
葉子對象,其下再也沒有其他的子節點,是遍歷的最小單位。
③、Composite 樹枝構件
樹枝對象,作用是組合樹枝節點和葉子節點形成一個樹形結構。
3、組合模式通用代碼實現
/**
* 個體和整體的抽象
*/
public abstract class Component {
// 個體和整體都有的共享
public void doSomething(){
// 通用業務邏輯
System.out.println("通用業務邏輯");
}
}
/**
* 樹枝節點
*/
public class Composite extends Component{
// 構件容器
private ArrayList< Component > componentArrayList = new ArrayList< >();
// 增加一個葉子節點或者樹枝節點
public void add(Component component){
this.componentArrayList.add(component);
}
// 刪除一個葉子節點或者樹枝節點
public void remove(Component component){
this.componentArrayList.remove(component);
}
// 獲取分支下所有葉子節點和樹枝節點
public List< Component > getChildren(){
return this.componentArrayList;
}
}
/**
* 葉子節點
*/
public class Leaf extends Component {
// 覆寫父類方法
@Override
public void doSomething() {
// 葉子節點邏輯
System.out.println("葉子節點邏輯");
}
}
測試:
public class ClientTest {
public static void main(String[] args) {
// 創建一個根節點
Composite root = new Composite();
root.doSomething();
// 創建一個樹枝構件
Composite branch = new Composite();
// 創建一個葉子節點
Leaf leaf = new Leaf();
// 串聯起來
root.add(branch);
branch.add(leaf);
display(root);
}
// 通過遞歸遍歷數
public static void display(Composite root){
for(Component c : root.getChildren()){
if(c instanceof Leaf){ // 葉子節點
c.doSomething();
}else{
display((Composite) c);
}
}
}
}
這里我們在舉一個例子:
假設我們在開發一個 OA 系統(辦公自動化系統)。公司的組織結構包含部門和員工兩種數據類型。其中,部門又可以包含子部門和員工。
我們希望在內存中構建整個公司的人員架構圖(部門、子部門、員工的隸屬關系),并且提供接口計算出部門的薪資成本(隸屬于這個部門的所有員工的薪資和)。
/**
* 部門類和員工類的抽象類
*/
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;
}
}
測試:
public class PersonClientTest {
private static final long ORGANIZATION_ROOT_ID = 1;
public static void main(String[] args) {
// 創建總部門
Department root = new Department(ORGANIZATION_ROOT_ID);
// 創建子部門
Department branch = new Department(2L);
// 創建員工
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){
// 根據 部門id 查詢數據庫 所有下屬部門 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);
}
// 根據部門id 查詢數據庫 其關聯員工所有 id
// List< Long > employeeIds = employeeRepo.getDepartmentEmployeeIds(department.getId());
List< Long > employeeIds = new ArrayList< >();
for (Long employeeId : employeeIds){
// 根據 employeeId 查詢數據庫得到 salary
// 假設為 1000
double salary = 1000d;
department.addSubNode(new Employee(employeeId,salary));
}
}
}
4、組合模式優點
①、高層模塊調用簡單
一棵樹形機構中的所有節點都是Component, 局部和整體對調用者來說沒有任何區別,也就是說, 高層模塊不必關心自己處理的是單個對象還是整個組合結構, 簡化了高層模塊的代碼。
②、節點自由增加
使用了組合模式后, 如果想增加一個樹枝節點、 葉子節點都很容易, 只要找到它的父節點就成, 非常容易擴展, 符合開閉原則, 對以后的維護非常有利。
5、組合模式應用場景
只要是樹形結構,就可以考慮使用組合模式。
①、維護和展示部分-整體關系的場景, 如樹形菜單、 文件和文件夾管理。
②、從一個整體中能夠獨立出部分模塊或功能的場景
-
接口
+關注
關注
33文章
8650瀏覽量
151409 -
數據
+關注
關注
8文章
7085瀏覽量
89204 -
容器
+關注
關注
0文章
496瀏覽量
22078 -
代碼
+關注
關注
30文章
4803瀏覽量
68752
發布評論請先 登錄
相關推薦
評論