如何在Java中实现复合模式?

彼得·米内苏(Peter Minesu)

我想实现一个复合模式Java,以便映射一个软件开发组织。因此,假设有多个项目经理和多个开发人员。每个开发人员仅分配给一个项目经理,并且每个开发人员都可以使用各种编程语言进行编码。项目经理带领开发人员,并确切地知道他们的工作量。

我对这种设计模式不是百分百确定,但是我认为这是此方案的完美用例,不是吗?

结果应如下所示:

我想查询项目经理,以检查所有能够使用特定编程语言(例如)进行编码的开发人员的工作量Java

这是我到目前为止的内容:

Employee.java:

public class Employee {

    private String name = null;

    public Employee() {
        name = "Noob";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

ProgrammingLanguages.java:

public enum ProgrammingLanguages {
    JAVA,
    JAVASCRIPT,
    C,
    PHP,
    SWIFT,
    PYTHON
}

ProjectManager.java:

import java.util.ArrayList;
import java.util.List;

public class ProjectManager extends Employee {

private List<Employee> employeeList = null;

public ProjectManager() {
    employeeList = new ArrayList<Employee>();
}

public List<Employee> getEmployees() {
    return employeeList;
}

public void setEmployees(List<Employee> employees) {
    employeeList = employees;
}

public int getTotalWorkload() {
    int workload = 0;
    for (Employee employee : employeeList) {
        workload += employee.getWorkload(); // Error! Cannot resolve method 'getWorkload()'
    }
    return workload;
}
}

开发商:

import java.util.ArrayList;
import java.util.List;

public class Developer extends Employee {

private List<ProgrammingLanguages> languagesList = null;

private int workload = 0;

public Developer() {
    languagesList = new ArrayList<ProgrammingLanguages>();
}

public void setLanguagesList(List<ProgrammingLanguages> languagesList) {
    this.languagesList = languagesList;
}

public void addProgrammingLanguage(ProgrammingLanguages language) {
    languagesList.add(language);
}

public List<ProgrammingLanguages> getLanguagesList() {
    return languagesList;
}

public void setWorkload(int workload) {
    this.workload = workload;
}

public int getWorkload() {
    return workload;
}

}

不幸的是,我在ProjectManager类中遇到了一个编译器错误,为什么?

提前致谢。

马蒂亚斯·埃克哈特(Matthias A. Eckhart)

是的,如果要映射树结构,则复合模式确实是正确的选择。参考您的示例,复合设计模式意味着您的类Employee充当节点,该类ProjectManager充当分支,该类Developer充当叶子。在这种情况下,合成图案的主要优点是可以均匀地处理合成对象。结果,您可以使用此特定的GoF设计模式来表示实例的整个层次结构。

您需要以下参与者:

  1. abstractEmployee必须声明组合物的界面和实现公共行为在一定程度上。
  2. ProjectManager类扩展abstractEmployee并实现了行为治疗Employee,你的情况的孩子,IDProjectManagerDeveloper实例。
  3. Developer还扩展了abstractEmployee,并且表示没有任何孩子一片叶子。

我使用您的示例代码来演示复合模式。请注意,它可能与您期望的结果有所不同,但是您可以将其作为参考。

Employee.java (节点):

package me.eckhart;

import java.util.List;

public abstract class Employee {

    private String name = null;
    public static final String OPERATION_NOT_SUPPORTED = "Operation not supported.";

    public String getName() {
        return name;
    }

    public Employee setName(String name) {
        if (name == null) throw new IllegalArgumentException("Argument 'name' is null.");
        this.name = name;
        return this;
    }

    public Employee addEmployee(Employee employee) {
        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED);
    }

    public List<Employee> getEmployees() {
        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED);
    }

    public Employee setEmployees(List<Employee> employees) {
        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED);
    }

    public Employee setLanguagesList(List<ProgrammingLanguages> languagesList) {
        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED);
    }

    public Employee addProgrammingLanguage(ProgrammingLanguages language) {
        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED);
    }

    public List<ProgrammingLanguages> getLanguagesList() {
        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED);
    }

    /* Composite operations. */

    public abstract int getWorkload(ProgrammingLanguages language);

    public abstract Employee setWorkload(int workload);

}

ProjectManager.java (分支):

package me.eckhart;

import java.util.ArrayList;
import java.util.List;

public class ProjectManager extends Employee {

    private List<Employee> employeeList = null;

    public ProjectManager() {
        this.employeeList = new ArrayList<>();
    }

    @Override
    public Employee addEmployee(Employee employee) {
        if (employee == null) throw new IllegalArgumentException("Argument 'employee' is null.");
        this.employeeList.add(employee);
        return this;
    }

    @Override
    public List<Employee> getEmployees() {
        return this.employeeList;
    }

    @Override
    public Employee setEmployees(List<Employee> employeeList) {
        if (employeeList == null) throw new IllegalArgumentException("Argument 'employeeList' is null.");
        this.employeeList = employeeList;
        return this;
    }

    /* Composite operations. */

    public int getWorkload(ProgrammingLanguages language) {
        int workload = 0;
        for (Employee employee : employeeList) {
            workload += employee.getWorkload(language);
        }
        return workload;
    }

    public Employee setWorkload(int workload) {
        throw new UnsupportedOperationException(Employee.OPERATION_NOT_SUPPORTED);
    }

}

Developer.java (叶子):

package me.eckhart;

import java.util.ArrayList;
import java.util.List;

public class Developer extends Employee {

    private List<ProgrammingLanguages> languagesList = null;

    private int workload = 0;

    public Developer() {
        this.languagesList = new ArrayList<>();
    }

    @Override
    public Employee setLanguagesList(List<ProgrammingLanguages> languagesList) {
        this.languagesList = languagesList;
        return this;
    }

    @Override
    public Employee addProgrammingLanguage(ProgrammingLanguages language) {
        this.languagesList.add(language);
        return this;
    }

    @Override
    public List<ProgrammingLanguages> getLanguagesList() {
        return this.languagesList;
    }

    /* Composite operations. */

    public Employee setWorkload(int workload) {
        if (workload < -1) throw new IllegalArgumentException("Workload cannot be negative.");
        this.workload = workload;
        return this;
    }

    public int getWorkload(ProgrammingLanguages language) {
        if (this.languagesList.contains(language)) return workload;
        return 0;
    }

}

ProgrammingLanguages.java (枚举):

package me.eckhart;

public enum ProgrammingLanguages {
    JAVA,
    JAVASCRIPT,
    C,
    PHP,
    SWIFT,
    PYTHON
}

我创建了一个单元测试,以演示如何访问一种特定编程语言的工作负载。

EmployeeTest.java (JUnit 4.11):

package me.eckhart;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class EmployeeTest {

    protected Employee projectManagerIt;

    @Before
    public void setUp() throws Exception {

        Employee webDevSr = new Developer();
        webDevSr.setName("Jane").addProgrammingLanguage(ProgrammingLanguages.JAVASCRIPT).addProgrammingLanguage(ProgrammingLanguages.PYTHON).setWorkload(10);
        Employee webDevJr = new Developer();
        webDevJr.setName("Alex").addProgrammingLanguage(ProgrammingLanguages.PHP).setWorkload(15);
        Employee projectManagerWebDev = new ProjectManager();
        projectManagerWebDev.setName("James").addEmployee(webDevSr).addEmployee(webDevJr);

        Employee softwareDevSr = new Developer();
        softwareDevSr.setName("Martin").addProgrammingLanguage(ProgrammingLanguages.C).addProgrammingLanguage(ProgrammingLanguages.JAVA).setWorkload(35);
        Employee softwareDevJr = new Developer();
        softwareDevJr.setName("John").addProgrammingLanguage(ProgrammingLanguages.JAVA).setWorkload(30);
        Employee projectManagerBackend = new ProjectManager();
        projectManagerBackend.setName("Tom").addEmployee(softwareDevSr).addEmployee(softwareDevJr);

        Employee freelanceSoftwareDev = new Developer();
        freelanceSoftwareDev.setName("Marco").addProgrammingLanguage(ProgrammingLanguages.JAVA).addProgrammingLanguage(ProgrammingLanguages.PYTHON).addProgrammingLanguage(ProgrammingLanguages.C).setWorkload(25);
        Employee freelanceWebDev = new Developer();
        freelanceWebDev.setName("Claudio").addProgrammingLanguage(ProgrammingLanguages.SWIFT).addProgrammingLanguage(ProgrammingLanguages.JAVASCRIPT).addProgrammingLanguage(ProgrammingLanguages.PHP).setWorkload(10);
        Employee freelanceProjectManager = new ProjectManager();
        freelanceProjectManager.setName("Angie").addEmployee(freelanceSoftwareDev).addEmployee(freelanceWebDev);

        projectManagerIt = new ProjectManager();
        projectManagerIt.setName("Peter").addEmployee(projectManagerWebDev).addEmployee(projectManagerBackend).addEmployee(freelanceProjectManager);

    }

    @Test
    public void testComposite() throws Exception {

        Assert.assertEquals(90, projectManagerIt.getWorkload(ProgrammingLanguages.JAVA));
        Assert.assertEquals(20, projectManagerIt.getWorkload(ProgrammingLanguages.JAVASCRIPT));
        Assert.assertEquals(60, projectManagerIt.getWorkload(ProgrammingLanguages.C));
        Assert.assertEquals(25, projectManagerIt.getWorkload(ProgrammingLanguages.PHP));
        Assert.assertEquals(10, projectManagerIt.getWorkload(ProgrammingLanguages.SWIFT));
        Assert.assertEquals(35, projectManagerIt.getWorkload(ProgrammingLanguages.PYTHON));

    }
}

UML类图如下所示:

UML_class_diagram_composite_design_pattern_GoF

setUp()方法中的代码EmployeeTest.java实现以下树结构:

Tree_structure_Composite_Pattern

组合设计模式的主要缺点是,您需要通过运行时检查来限制某些操作,因为客户端通常不知道他们是在处理ProjectManager(分支Developer)实例还是(叶子)实例。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章