容許你將對象組合成樹形結構來表現「總體/部分」層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合。數據結構
組合模式適用於建立複雜的對象,這個對象包含某些個別的對象以及這些對象的組合。app
從操做的角度而言,客戶端對於 個別對象/組合 的操做是一致的。ide
如圖所示,總公司下屬有多個部門,而子公司能夠視爲多個部門的組合。ui
整個數據結構呈樹狀,完美契合組合模式的應用場景。spa
在這個場景中:code
@Data @AllArgsConstructor @ToString public abstract class CompanyItem { protected String name; protected void addCompanyItem(CompanyItem companyItem) { throw new UnsupportedOperationException("Not support to add companyItem"); } protected void removeCompanyItem(CompanyItem companyItem) { throw new UnsupportedOperationException("Not support to remove companyItem"); } protected abstract void lineOfDuty(); protected abstract void showStructure(int depth); }
public final class Company extends CompanyItem { private List<CompanyItem> childCompanyItems = new ArrayList<>(); public Company(String name) { super(name); } @Override public void addCompanyItem(CompanyItem component) { childCompanyItems.add(component); } @Override public void removeCompanyItem(CompanyItem component) { childCompanyItems.remove(component); } @Override public void lineOfDuty() { childCompanyItems.forEach(companyItem -> companyItem.lineOfDuty()); } @Override public void showStructure(int depth) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < depth; ++i) { builder.append("-"); } System.out.println(builder.append(name)); childCompanyItems.forEach(companyItem -> companyItem.showStructure(depth + 1)); } }
public final class FinanceDepartment extends CompanyItem { public FinanceDepartment(String name) { super(name); } @Override public void lineOfDuty() { System.out.println(name + ", treasurer is in charge of payroll"); } @Override public void showStructure(int depth) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < depth; ++i) { builder.append("-"); } System.out.println(builder.append(name)); } }
public final class HRDepartment extends CompanyItem { public HRDepartment(String name) { super(name); } @Override public void lineOfDuty() { System.out.println(name + ", HR is responsible for recruiting new employees"); } @Override public void showStructure(int depth) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < depth; ++i) { builder.append("-"); } System.out.println(builder.append(name)); } }
private CompanyItem createParentCompany() { CompanyItem parentCompany = new Company("Shanghai parent company"); parentCompany.addCompanyItem(new HRDepartment("Parent company HR department")); CompanyItem southChildCompany = new Company("South child company"); southChildCompany.addCompanyItem(new HRDepartment("South child company HR department")); parentCompany.addCompanyItem(southChildCompany); CompanyItem hongKongOffice = new Company("HongKong office"); hongKongOffice.addCompanyItem(new FinanceDepartment("Hongkong office Finance department")); southChildCompany.addCompanyItem(hongKongOffice); parentCompany.addCompanyItem(new FinanceDepartment("Parent company Finance department")); return parentCompany; } @Test void testComposite() { CompanyItem parentCompany = createParentCompany(); parentCompany.showStructure(1); System.out.println("==========================="); parentCompany.lineOfDuty(); }