A mode defines a
composition mode: the objects are combined into a tree structure to represent a "part-to-whole" hierarchy, and the composition mode enables users to use a single object and a composite object with consistency.
Two Combination Patterns Example
1 Pattern Analysis
We use the company organizational chart to illustrate this pattern.
After analysis, we get the static class diagram of this mode as follows:
2 Code example
2.1 Establish employee abstract class
package com.demo.composite; /** * Worker interface * * @author * */ public abstract class Staff { // employee ID protected String no; // employee name protected String name; // Position protected String position; // salary protected float salary; // private property length string private int length; // Construction method public Staff(String no, String name, String position, float salary) { this.no = no; this.name = name; this.position = position; this.salary = salary; // Calculate the total length in bytes this.length += (no == null || "".equals(no.trim())) ? 0 : no.getBytes().length; this.length += (name == null || "".equals(name.trim())) ? 0 : name .getBytes().length; this.length += (position == null || "".equals(position.trim())) ? 0 : position.getBytes().length; this.length += String.valueOf(salary).getBytes().length; } // Get basic user information public void printUserBaseInfo() { System.out.println("|" + this.no + " " + this.name + " " + this.position + " " + this.salary); } // add employee information public abstract void add(Staff staff); // delete employee public abstract Staff remove(String no); // print employee information public abstract void printEmployeesInfo(int layer); // print some characters protected void printChar(int layer) { for (int j = 0; j < layer * 2; j++) { System.out.print("-"); } } // private method prints a line protected void printLine() { System.out.print("+"); for (int i = 0; i < this.length + 4; i++) { System.out.print("-"); } System.out.println("-"); } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPosition() { return position; } public void setPosition(String position) { this.position = position; } public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; } }
2.2 Create a manager
package com.demo.composite.sub; import java.util.ArrayList; import com.demo.composite.Staff; /** * Managers (people with other employees) * * @author * */ public class Manager extends Staff { // store employee information private final ArrayList<Staff> arrayList = new ArrayList<Staff>(); // Construction method public Manager(String no, String name, String position, float salary) { super(no, name, position, salary); } /** * Add an employee */ @Override public void add(Staff staff) { this.arrayList.add(staff); } /** * Delete employee information */ @Override public Staff remove(String no) { Staff staff = null; if (no != null && !"".equals(no.trim())) { for (int i = 0; i < this.arrayList.size(); i++) { if (this.arrayList.get(i) == null) { continue; } if (no.equals(this.arrayList.get(i).getNo())) { staff = this.arrayList.remove(i); break; } } } return staff; } /** * Print employee information */ @Override public void printEmployeesInfo(int layer) { int tmpLayer = ++layer; for (int i = 0; i < this.arrayList.size(); i++) { if (this.arrayList.get(i) == null) { continue; } // Print'-' printChar(tmpLayer); // print employee basic information this.arrayList.get(i).printUserBaseInfo(); // print employee information this.arrayList.get(i).printEmployeesInfo(tmpLayer); } } }
2.3 Create ordinary employees
package com.demo.composite.sub; import com.demo.composite.Staff; /** * Ordinary employees (people who really work) * * @author * */ public class Employees extends Staff { // Construction method public Employees(String no, String name, String position, float salary) { super(no, name, position, salary); } /** * Add employee information */ @Override public void add(Staff staff) { return; } /** * Delete employee information */ @Override public Staff remove(String no) { // directly return null return null; } /** * Print employee information */ @Override public void printEmployeesInfo(int layer) { return; } }
2.4 Client Test
package com.demo; import com.demo.composite.Staff; import com.demo.composite.sub.Employees; import com.demo.composite.sub.Manager; /** * Main application * * @author * */ public class Client { /** * @param args */ public static void main(String[] args) { // Company CEO Staff boss = new Manager("1", "大老板", "CEO", 100000); /** * There are several department managers under the CEO */ // Finance Manager Staff financeManager = new Manager("11", "Mr. Zhang", "Finance Manager", 60000); // HR manager Staff personnelManager = new Manager("12", "Mr. Wang", "Personnel Manager", 60000); // technical manager Staff technicalManager = new Manager("13", "Mr. Chen", "Technical Manager", 60000); /** * The technical department also has assistants and several supervisors */ // technical department assistant Staff deptAssistant = new Manager("1301", "Assistant Wang", "Dept Assistant", 20000); // Head of technical department 1 Staff deptManager1 = new Manager("1302", "Supervisor 1", "Technical Supervisor", 30000); /** * There are also software engineers under the technical director deptManager1 (the one who does the final work) */ Staff softwareEngineer1 = new Employees("1302001", "Zhang San", "Software Engineer", 5000); Staff softwareEngineer2 = new Employees("1302002", "Li Si", "Software Engineer", 5500); Staff softwareEngineer3 = new Employees("1302003", "Wang Wu", "Software Engineer", 4500); // Add employee information for technical supervisor 1 deptManager1.add(softwareEngineer1); deptManager1.add(softwareEngineer2); deptManager1.add(softwareEngineer3); // Head of technical department 2 Staff deptManager2 = new Manager("1303", "Supervisor 2", "Technical Supervisor", 30000); // Added for Technical Manager: Department Assistant, Technical Supervisor 1 and Technical Supervisor 2 technicalManager.add(deptAssistant); technicalManager.add(deptManager1); technicalManager.add(deptManager2); // Marketing Manager Staff marketingManager = new Manager("14", "Mr. Wu", "Marketing Manager", 60000); // Added for CEO: Finance Manager, HR Manager, Technical Manager and Marketing Manager boss.add(financeManager); boss.add(personnelManager); boss.add(technicalManager); boss.add(marketingManager); // print CEO info boss.printUserBaseInfo(); // Print the employee information of the CEO boss.printEmployeesInfo(1); } }
The results are as follows:
|1 Big Boss CEO 100000.0
----|11 Mr. Zhang, Manager of Finance Department 60000.0
----|12 Mr. Wang, Manager of Personnel Department 60000.0
----|13 Mr. Chen, Manager of Technical Department 60000.0
------|1301 Assistant Wang Department Assistant 20000.0
------|1302 Supervisor 1 Technical Supervisor 30000.0
--------|1302001 Zhang San Software Engineer 5000.0
--------|1302002 Li Si Software Engineer 5500.0
-- ------|1302003 Wang Wu Software Engineer 4500.0
------|1303 Supervisor 2 Technical Supervisor 30000.0
----|14 Wu General Manager of Marketing Department 60000.0
Three principles of pattern design
1 Unified treatment of individual objects and composite objects
2 Abstract-oriented programming
Four use cases
1 When you want to represent a "part-whole" hierarchy of objects.
2 When users are expected to ignore the difference between a composite object and a single object, the user will use all the objects in the composite structure uniformly.
The static class diagram of the combined mode is as follows