在这里,我为您提供了另一个有用的设计模式-复合设计模式。我将尝试指出在为您实现复合模式时要记住的关键功能。
Composite Design Pattern 该复合设计模式是指“将对象组合成树形结构来表示部分-整体层次结构。Composite模式使得客户对单个对象和复合对象的统一”。
以下是Composite Design Pattern中使用的classes/objects的列表,该列表有四个:
Component – Component是用于组成对象的接口(或抽象类),以及用于访问/处理其子组件或节点组件的方法。它还实现了一个默认接口,以定义所有组件类的通用功能/行为。 Leaf – 叶子类定义了一个具体的组件类,没有任何进一步的组成。叶子类实现组件接口。它仅在最后执行命令/任务。 Composite – Composite类定义了一个具体的组件类,该类存储其子组件。复合类实现组件接口。它将命令/任务转发到它包含的复合对象。它还可以在转发interact/manipulate之前和之后执行其他操作。 Client –Client 类使用组件接口来交互/操纵合成中的对象(Leaf and Composite)。
为了更好地理解这一点,让我们看一个在组织中工作的员工的示例。
Steps 我们创建一个接口来定义要作为复合对象和叶对象执行的功能。下面是Worker接口的代码,其中包含assignWork()和方法performWork()。Work在示例中,该界面将充当复合模式的组成部分。
package org.trishinfotech.composite; public interface Worker { void assignWork(Employee manager, Work work); void performWork(); }
工作类被定义为如下:
package org.trishinfotech.composite; import java.util.ArrayList; import java.util.List; public class Work { private Calculator workType; private List<String> work = new ArrayList<String>(); public Work(Calculator workType, List<String> work) { super(); this.workType = workType; this.work = work; } public Calculator getWorkType() { return workType; } public void setWorkType(Calculator workType) { this.workType = workType; } public List<String> getWork() { return work; } public void setWork(List<String> work) { this.work = work; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Work [workType=").append(workType).append(", work=").append(work).append("]"); return builder.toString(); } }
为了简化示例,在这里我仅处理简单的计算,例如阶乘值和回文和Armstrong检验。由于Pandirome也可以是字符串,因此我在Work课堂上一直从事String的工作。下面的类定义了执行阶乘,回文和阿姆斯特朗的算法/公式。这是计算器 枚举的代码:
package org.trishinfotech.composite; import java.math.BigInteger; public enum Calculator { FACTORIAL { @Override public String calculate(String value) { String answer = "NA"; try { long longValue = Long.parseLong(value); BigInteger factorialValue = BigInteger.valueOf(1); for (long i = 1; i <= longValue; i++) { factorialValue = factorialValue.multiply(BigInteger.valueOf(i)); } answer = factorialValue.toString(); } catch (NumberFormatException exp) { System.out.println("Can't calculate factorial of " + value); } return answer; } }, PALINDROME { @Override public String calculate(String value) { String answer = "false"; if (value != null && !value.trim().isEmpty()) { String reverse = (new StringBuilder(value).reverse().toString()); answer = Boolean.toString(reverse.equals(value)); } return answer; } }, ARMSTRONG { @Override public String calculate(String value) { String answer = "false"; try { long longValue = Long.parseLong(value); long number = longValue; long armstrongValue = 0; while (number != 0) { long temp = number % 10; armstrongValue = armstrongValue + temp * temp * temp; number /= 10; } answer = Boolean.toString(String.valueOf(armstrongValue).equals(value)); } catch (NumberFormatException exp) { System.out.println("Can't calculate armstrong of " + value); } return answer; } }; public abstract String calculate(String value); }
I have created these algorithms as enums. To read more on Java-Enums, please refer to my article (Java Enums: How to Make Enums More Useful).
We will create an abstract class of Employee to carry the common code for all various concrete subclasses of the employees.
package org.trishinfotech.composite; public abstract class Employee implements Worker { protected long employeeId; protected String employeeName; protected String designation; protected Department department; public Employee(long employeeId, String employeeName, String designation, Department department) { super(); this.employeeId = employeeId; this.employeeName = employeeName; this.designation = designation; this.department = department; } public long getEmployeeId() { return employeeId; } public void setEmployeeId(long employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getDesignation() { return designation; } public void setDesignation(String designation) { this.designation = designation; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } public abstract int teamSize(); public String fullDetails() { StringBuilder builder = new StringBuilder(); builder.append("Employee [").append(employeeId).append(", ").append(employeeName).append(", ") .append(designation).append(", ").append(department).append(", Team=").append(teamSize()).append("]"); return builder.toString(); } public String shortDetails() { StringBuilder builder = new StringBuilder(); builder.append("'").append(employeeName).append("'"); return builder.toString(); } @Override public String toString() { return shortDetails(); } }
The Employeeclass declares abstract method teamSize() which I will use to split the work load assigned from a manager to anEngineer. So teamSize() will will be 1 forEngineer where as it will give the number of employees theManager is managing.
TheEngineer class is as below:
package org.trishinfotech.composite; import java.util.ArrayList; import java.util.List; public class Engineer extends Employee { private List<Work> works = new ArrayList<Work>(); public Engineer(long employeeId, String employeeName, String designation, Department department) { super(employeeId, employeeName, designation, department); } @Override public int teamSize() { return 1; } @Override public void assignWork(Employee manager, Work work) { this.works.add(work); System.out.println(this + " has assigned work of '" + work + "' by manager " + manager); } @Override public void performWork() { System.out.println(this + " is performing work of '" + works + "'"); works.stream().forEach(work -> { work.getWork().stream().forEach(value -> { Calculator calculator = work.getWorkType(); System.out.println(this + " has result of work of '" + work + "' as : " + calculator.calculate(value)); }); }); works.clear(); } }
We will create the Manager class to use as the composite object, and we will have another Employee object as a collection via the composition. The Manager class is as below:
package org.trishinfotech.composite; import java.util.ArrayList; import java.util.List; public class Manager extends Employee { List<Employee> managingEmployees = new ArrayList<Employee>(); public Manager(long employeeId, String employeeName, String designation, Department department) { super(employeeId, employeeName, designation, department); } public boolean manages(Employee employee) { return managingEmployees.add(employee); } public boolean stopManaging(Employee employee) { return managingEmployees.remove(employee); } @Override public int teamSize() { return managingEmployees.stream().mapToInt(employee -> employee.teamSize()).sum(); } @Override public void assignWork(Employee manager, Work work) { System.out.println(this + " has assigned work of '" + work + "' by manager " + manager); System.out.println(); System.out.println(this + " distributing work '" + work + "' to managing-employees.."); int fromIndex = 0; int toIndex = 0; int totalWork = work.getWork().size(); List<String> assignWork = null; while (toIndex < totalWork) { for (Employee employee : managingEmployees) { System.out.println("Assigning to " + employee); int size = employee.teamSize(); toIndex = fromIndex + size; assignWork = work.getWork().subList(fromIndex, toIndex); if (assignWork.isEmpty()) { return; } employee.assignWork(this, new Work(work.getWorkType(), assignWork)); fromIndex = toIndex; } break; } } @Override public void performWork() { System.out.println(this + " is asking his managing employees to perform assigned work"); System.out.println(); managingEmployees.stream().forEach(employee -> employee.performWork()); System.out.println(); System.out.println(this + " has completed assigned work with the help of his managing employees"); System.out.println(); } }
We define Work in the property file instead of hard-coding into theMain class. The work.propertiesis defined as below:
Calculate.Palindrome=1234321, 12341234, ABCDEDCBA, 4567887654, XYZZYX, 45676543, 3456543 Calculate.Armstrong=153, 8208, 2104, 4210818, 345321, 32164049651, 876412347 Calculate.Factorial=20, 43, 15, 120, 543, 35, 456, 432, 350, 44, 26, 17, 8
The Main class usesWorkLoader class to load work from the work.properties. TheWorkLoader class is defined as below:
package org.trishinfotech.composite; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.Set; public class WorkLoader { protected Properties properties = new Properties(); public WorkLoader(String fileName) { try (InputStream input = new FileInputStream(fileName)) { // load a properties file properties.load(input); } catch (IOException exp) { exp.printStackTrace(); } } public Properties getProperties() { return properties; } public List<Work> getWorkList() { List<Work> workList = new ArrayList<Work>(); Set<Object> keys = properties.keySet(); for (Object key : keys) { String workType = key.toString().substring("Calculate".length() + 1).toUpperCase(); String values = properties.getProperty(key.toString()); Work work = new Work(Calculator.valueOf(workType), Arrays.asList(values.split(", "))); workList.add(work); } return workList; } }
最后,我们将把Main类编写为,Client以执行和测试我们的复合模式代码。
package org.trishinfotech.composite; public class Main { public static void main(String[] args) { Engineer ajay = new Engineer(1001l, "Ajay", "Developer", Department.ENG); Engineer vijay = new Engineer(1002l, "Vijay", "SR. Developer", Department.ENG); Engineer jay = new Engineer(1003l, "Jay", "Lead", Department.ENG); Engineer martin = new Engineer(1004l, "Martin", "QA", Department.ENG); Manager kim = new Manager(1005l, "Kim", "Manager", Department.ENG); Engineer anders = new Engineer(1006l, "Andersen", "Developer", Department.ENG); Manager niels = new Manager(1007l, "Niels", "Sr. Manager", Department.ENG); Engineer robert = new Engineer(1008l, "Robert", "Developer", Department.ENG); Manager rachelle = new Manager(1009l, "Rachelle", "Product Manager", Department.ENG); Engineer shailesh = new Engineer(1010l, "Shailesh", "Engineer", Department.ENG); kim.manages(ajay); kim.manages(martin); kim.manages(vijay); niels.manages(jay); niels.manages(anders); niels.manages(shailesh); rachelle.manages(kim); rachelle.manages(robert); rachelle.manages(niels); WorkLoader workLoad = new WorkLoader("work.properties"); workLoad.getWorkList().stream().forEach(work -> { rachelle.assignWork(rachelle, work); }); rachelle.performWork(); } }
下面是程序的输出:
'Rachelle' has assigned work of 'Work [workType=FACTORIAL, work=[20, 43, 15, 120, 543, 35, 456, 432, 350, 44, 26, 17, 8]]' by manager 'Rachelle' 'Rachelle' distributing work 'Work [workType=FACTORIAL, work=[20, 43, 15, 120, 543, 35, 456, 432, 350, 44, 26, 17, 8]]' to managing-employees.. Assigning to 'Kim' 'Kim' has assigned work of 'Work [workType=FACTORIAL, work=[20, 43, 15]]' by manager 'Rachelle' 'Kim' distributing work 'Work [workType=FACTORIAL, work=[20, 43, 15]]' to managing-employees.. Assigning to 'Ajay' 'Ajay' has assigned work of 'Work [workType=FACTORIAL, work=[20]]' by manager 'Kim' Assigning to 'Martin' 'Martin' has assigned work of 'Work [workType=FACTORIAL, work=[43]]' by manager 'Kim' Assigning to 'Vijay' 'Vijay' has assigned work of 'Work [workType=FACTORIAL, work=[15]]' by manager 'Kim' Assigning to 'Robert' 'Robert' has assigned work of 'Work [workType=FACTORIAL, work=[120]]' by manager 'Rachelle' Assigning to 'Niels' 'Niels' has assigned work of 'Work [workType=FACTORIAL, work=[543, 35, 456]]' by manager 'Rachelle' 'Niels' distributing work 'Work [workType=FACTORIAL, work=[543, 35, 456]]' to managing-employees.. Assigning to 'Jay' 'Jay' has assigned work of 'Work [workType=FACTORIAL, work=[543]]' by manager 'Niels' Assigning to 'Andersen' 'Andersen' has assigned work of 'Work [workType=FACTORIAL, work=[35]]' by manager 'Niels' Assigning to 'Shailesh' 'Shailesh' has assigned work of 'Work [workType=FACTORIAL, work=[456]]' by manager 'Niels' 'Rachelle' has assigned work of 'Work [workType=PALINDROME, work=[1234321, 12341234, ABCDEDCBA, 4567887654, XYZZYX, 45676543, 3456543]]' by manager 'Rachelle' 'Rachelle' distributing work 'Work [workType=PALINDROME, work=[1234321, 12341234, ABCDEDCBA, 4567887654, XYZZYX, 45676543, 3456543]]' to managing-employees.. Assigning to 'Kim' 'Kim' has assigned work of 'Work [workType=PALINDROME, work=[1234321, 12341234, ABCDEDCBA]]' by manager 'Rachelle' 'Kim' distributing work 'Work [workType=PALINDROME, work=[1234321, 12341234, ABCDEDCBA]]' to managing-employees.. Assigning to 'Ajay' 'Ajay' has assigned work of 'Work [workType=PALINDROME, work=[1234321]]' by manager 'Kim' Assigning to 'Martin' 'Martin' has assigned work of 'Work [workType=PALINDROME, work=[12341234]]' by manager 'Kim' Assigning to 'Vijay' 'Vijay' has assigned work of 'Work [workType=PALINDROME, work=[ABCDEDCBA]]' by manager 'Kim' Assigning to 'Robert' 'Robert' has assigned work of 'Work [workType=PALINDROME, work=[4567887654]]' by manager 'Rachelle' Assigning to 'Niels' 'Niels' has assigned work of 'Work [workType=PALINDROME, work=[XYZZYX, 45676543, 3456543]]' by manager 'Rachelle' 'Niels' distributing work 'Work [workType=PALINDROME, work=[XYZZYX, 45676543, 3456543]]' to managing-employees.. Assigning to 'Jay' 'Jay' has assigned work of 'Work [workType=PALINDROME, work=[XYZZYX]]' by manager 'Niels' Assigning to 'Andersen' 'Andersen' has assigned work of 'Work [workType=PALINDROME, work=[45676543]]' by manager 'Niels' Assigning to 'Shailesh' 'Shailesh' has assigned work of 'Work [workType=PALINDROME, work=[3456543]]' by manager 'Niels' 'Rachelle' has assigned work of 'Work [workType=ARMSTRONG, work=[153, 8208, 2104, 4210818, 345321, 32164049651, 876412347]]' by manager 'Rachelle' 'Rachelle' distributing work 'Work [workType=ARMSTRONG, work=[153, 8208, 2104, 4210818, 345321, 32164049651, 876412347]]' to managing-employees.. Assigning to 'Kim' 'Kim' has assigned work of 'Work [workType=ARMSTRONG, work=[153, 8208, 2104]]' by manager 'Rachelle' 'Kim' distributing work 'Work [workType=ARMSTRONG, work=[153, 8208, 2104]]' to managing-employees.. Assigning to 'Ajay' 'Ajay' has assigned work of 'Work [workType=ARMSTRONG, work=[153]]' by manager 'Kim' Assigning to 'Martin' 'Martin' has assigned work of 'Work [workType=ARMSTRONG, work=[8208]]' by manager 'Kim' Assigning to 'Vijay' 'Vijay' has assigned work of 'Work [workType=ARMSTRONG, work=[2104]]' by manager 'Kim' Assigning to 'Robert' 'Robert' has assigned work of 'Work [workType=ARMSTRONG, work=[4210818]]' by manager 'Rachelle' Assigning to 'Niels' 'Niels' has assigned work of 'Work [workType=ARMSTRONG, work=[345321, 32164049651, 876412347]]' by manager 'Rachelle' 'Niels' distributing work 'Work [workType=ARMSTRONG, work=[345321, 32164049651, 876412347]]' to managing-employees.. Assigning to 'Jay' 'Jay' has assigned work of 'Work [workType=ARMSTRONG, work=[345321]]' by manager 'Niels' Assigning to 'Andersen' 'Andersen' has assigned work of 'Work [workType=ARMSTRONG, work=[32164049651]]' by manager 'Niels' Assigning to 'Shailesh' 'Shailesh' has assigned work of 'Work [workType=ARMSTRONG, work=[876412347]]' by manager 'Niels' 'Rachelle' is asking his managing employees to perform assigned work 'Kim' is asking his managing employees to perform assigned work 'Ajay' is performing work of '[Work [workType=FACTORIAL, work=[20]], Work [workType=PALINDROME, work=[1234321]], Work [workType=ARMSTRONG, work=[153]]]' 'Ajay' has result of work of 'Work [workType=FACTORIAL, work=[20]]' as : 2432902008176640000 'Ajay' has result of work of 'Work [workType=PALINDROME, work=[1234321]]' as : true 'Ajay' has result of work of 'Work [workType=ARMSTRONG, work=[153]]' as : true 'Martin' is performing work of '[Work [workType=FACTORIAL, work=[43]], Work [workType=PALINDROME, work=[12341234]], Work [workType=ARMSTRONG, work=[8208]]]' 'Martin' has result of work of 'Work [workType=FACTORIAL, work=[43]]' as : 60415263063373835637355132068513997507264512000000000 'Martin' has result of work of 'Work [workType=PALINDROME, work=[12341234]]' as : false 'Martin' has result of work of 'Work [workType=ARMSTRONG, work=[8208]]' as : false 'Vijay' is performing work of '[Work [workType=FACTORIAL, work=[15]], Work [workType=PALINDROME, work=[ABCDEDCBA]], Work [workType=ARMSTRONG, work=[2104]]]' 'Vijay' has result of work of 'Work [workType=FACTORIAL, work=[15]]' as : 1307674368000 'Vijay' has result of work of 'Work [workType=PALINDROME, work=[ABCDEDCBA]]' as : true 'Vijay' has result of work of 'Work [workType=ARMSTRONG, work=[2104]]' as : false 'Kim' has completed assigned work with the help of his managing employees 'Robert' is performing work of '[Work [workType=FACTORIAL, work=[120]], Work [workType=PALINDROME, work=[4567887654]], Work [workType=ARMSTRONG, work=[4210818]]]' 'Robert' has result of work of 'Work [workType=FACTORIAL, work=[120]]' as : 6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000 'Robert' has result of work of 'Work [workType=PALINDROME, work=[4567887654]]' as : true 'Robert' has result of work of 'Work [workType=ARMSTRONG, work=[4210818]]' as : false 'Niels' is asking his managing employees to perform assigned work 'Jay' is performing work of '[Work [workType=FACTORIAL, work=[543]], Work [workType=PALINDROME, work=[XYZZYX]], Work [workType=ARMSTRONG, work=[345321]]]' 'Jay' has result of work of 'Work [workType=FACTORIAL, work=[543]]' as : 872891556790260456843586366934462570217404467584986862157951660218033476207283552939973350537069217537549478114229971312262991181125700413163606116971183695586311579361173915852193241844683585564114537080099157013082576149573523335369738442355599816710804068865355684599942047453968407440725166640261015140054933542126214585902983116193907129111747665196041855032660956095883694974186998924247749529335931094092429725640658310042199668214202637924631140057800119930627800378541111012271243379033822559451085315416955672912791395237932595257653475479021208979154389591618595449855779925751308303314870067464075830210893226767964127916083986194604372529850059441599156750579670067110415997949767860963439005485252514342425180564330056392659552281473502353159284918610493411467800558076001750687023376509841526414457026571388047691226042613278047076078395826335028468047405871941546558134196554638340479908186429178241794558954878506078646531853505428187507441610683354213870320835243780540993795316813622383436151335642255741817696689682127415809984693167490611336830354021351607247261703154384913620088006020923947745280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 'Jay' has result of work of 'Work [workType=PALINDROME, work=[XYZZYX]]' as : true 'Jay' has result of work of 'Work [workType=ARMSTRONG, work=[345321]]' as : false 'Andersen' is performing work of '[Work [workType=FACTORIAL, work=[35]], Work [workType=PALINDROME, work=[45676543]], Work [workType=ARMSTRONG, work=[32164049651]]]' 'Andersen' has result of work of 'Work [workType=FACTORIAL, work=[35]]' as : 10333147966386144929666651337523200000000 'Andersen' has result of work of 'Work [workType=PALINDROME, work=[45676543]]' as : false 'Andersen' has result of work of 'Work [workType=ARMSTRONG, work=[32164049651]]' as : false 'Shailesh' is performing work of '[Work [workType=FACTORIAL, work=[456]], Work [workType=PALINDROME, work=[3456543]], Work [workType=ARMSTRONG, work=[876412347]]]' 'Shailesh' has result of work of 'Work [workType=FACTORIAL, work=[456]]' as : 150777392777717065903328562798297482932764849966301315324902295697797980802999492049275470580840593582700556154654997912467653672836190567363944536581444396786039028419417159553169852939652733499484374432647121409002713034716885273557660568294514238651304204026421026217797122437474581042706674997505548774529387552185264469304745879944335896334980134727576771262477699704913814778801164976379963316514713032786305083016847394455111607701177156363125206697642497352441989049637406799105387152093299654856194446887474831405921359722324720996553956200165400519069670468845686118517860926559421327845227712982865242890852011587912148558934925229259778865164753102371910801614732061965104129730561590839408147446252948841011789641706225763887234100676084552005497753764496546383864694159909979495432469993306110242973486330432796522331628915418533758582252153753291412897349335363154308911927972242304805109760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 'Shailesh' has result of work of 'Work [workType=PALINDROME, work=[3456543]]' as : true 'Shailesh' has result of work of 'Work [workType=ARMSTRONG, work=[876412347]]' as : false 'Niels' has completed assigned work with the help of his managing employees 'Rachelle' has completed assigned work with the help of his managing employees
在这里,我没有使用并发来简化示例。请根据您的选择随意完善该示例。
原文链接:http://codingdict.com