http://www.tuicool.com/articles/ra6BJb
现在,我们需要设计一个项目管理系统,目前我们收集到了如下这些需求:
- REQ1:一个项目内有多名项目成员
- REQ2:一名项目成员只能被指派给一个项目
- REQ3:一个项目内仅有一名项目成员被指派为项目经理负责管理项目
- REQ4:所有项目成员均是公司员工
- REQ5:公司员工的薪水由基本工资和项目奖金组合而成
- REQ6:项目经理的项目奖金由项目的成败决定
- REQ7:项目中包含项目计划
- REQ8:一个项目计划由多个项目计划项组成
根据上面的需求描述,我们首先识别出若干个概念名词:
- 项目(Project)
- 项目成员(Project Member)
- 项目经理(Project Manager)
- 公司员工(Employee)
- 薪水(Salary)
- 基本工资(Base Salary)
- 项目奖金(Project Bonus)
- 项目计划(Schedule)
- 项目计划项(Schedule Item)
根据需求 “REQ4:所有项目成员均是公司员工”,我们可以得到 Employee 与 ProjectMember 的关系。
类 ProjectMember 实现了抽象类 Employee。Employee 类中包含计算薪水(Salary)操作,并负责封装需求 “REQ5:公司员工的薪水由基本工资和项目奖金组合而成”。ProjectMember 类覆写父类的薪水计算方法。
@H_
502_78@
1 public abstract class Employee
2 {
3 public Employee(
int id,
string name)
4 {
5 ID =
id;
6 Name =
name;
7 }
8
9 int ID {
get;
private set; }
10 string Name {
11
12 double CalculateSalary()
13 14 return GetBaseSalary() +
GetProjectBonus();
15 16
17 protected GetBaseSalary();
18 19 }
20
21 ProjectMember : Employee
22 23 public ProjectMember(
24 :
base(id,name)
25 26 27
28 public Project AssignedProject {
29
30 void AssignProject(Project project)
31 32 AssignedProject =
project;
33 34
35 override double GetBaseSalary() {
return 100036 double GetProjectBonus() {
20037 }
根据需求 “REQ3:一个项目内仅有一名项目成员被指派为项目经理负责管理项目”,可以推断出 ProjectManager 与 ProjectMember 的关系。
ProjectManager 继承自 ProjectMember。ProjectMember 类覆写父类的薪水计算方法,以实现需求 “REQ6:项目经理的项目奖金由项目的成败决定”。
ProjectManager : ProjectMember
public ProjectManager(4 : 5 6 7
8 20009
GetProjectBonus()
11 12 return AssignedProject.IsSuccess ? 800 : 0;
14 }
由下面三个需求可以识别出 Project 与 ProjectMember/ProjectManager 之间的关系。
REQ1:一个项目内有多名项目成员
REQ2:一名项目成员只能被指派给一个项目
REQ3:一个项目内仅有一名项目成员被指派为项目经理负责管理项目
Project 聚合(Aggregation)了 ProjectMember,ProjectMember 当不在该项目中时仍然可以存在,比如转去做其他项目。
Project 关联(Association)了 ProjectManager,ProjectManager 当不在该项目时,需要转换为 ProjectMember。
ProjectManager 的薪水将由所负责的项目的成败决定,会调用 Project 的状态以计算薪水。
Project
private ProjectManager _manager;
4 private List<ProjectMember> _members = new List<ProjectMember>();
5 private Schedule _schedule = new Schedule();
6
7 public Project( name,ProjectManager manager)
8 9 Name =10 _manager = manager;
12
13 14 public ProjectManager Manager { get { return _manager; } }
15 public ReadOnlyCollection<ProjectMember> Members { _members.AsReadOnly(); } }
16 public Schedule Schedule { _schedule; } }
bool IsSuccess { return (new Random().Next(1,100) % 2) > ; } }
18
19 void AssignMembers(IEnumerable<ProjectMember> members)
20 21 _members.AddRange(members);
22 _members.ForEach(m => m.AssignProject(this));
23 24
25 AddScheduleItem(ScheduleItem item)
27 _schedule.Add(item);
28 29 }
根据需求 “REQ7:项目中包含项目计划” 可得出 Project 与 Schedule 的关系。
根据需求 “REQ8:一个项目计划由多个项目计划项组成” 可得出 Schedule 与 ScheduleItem 的关系。
Project 聚合(Aggregation)了 Schedule。Schedule 由多个 ScheduleItem 组成(Composition)。
class Schedule : List<ScheduleItem>
3 4
5 ScheduleItem
string Description { public DateTime BeginTime { public DateTime EndTime { 10 }
由此,我们得到了满足全部需求的类图:
现在,我们可通过以上类的定义来组织业务逻辑。
Program
static void Main([] args)
5 ProjectManager manager = new ProjectManager(@"Dennis Gao");
6 ProjectMember member2 = new ProjectMember(2,0)">Super Man7 ProjectMember member3 = 3,0)">Iron Man8 ProjectMember member4 = Spider Man10 var projectMembers = () { manager,member2,member3,member4 };
12 Project project = new Project("EarnMoney,manager);
project.AssignMembers(projectMembers);
14
15 ScheduleItem item1 = ScheduleItem()
16 {
17 Description = Team Building18 BeginTime = DateTime.Now.AddDays(5),153)">19 EndTime = DateTime.Now.AddDays(6 };
project.AddScheduleItem(item1);
22
23 Console.WriteLine(Salary List of Project [{0}] Members:24 foreach (var member in project.Members)
Console.WriteLine(
27 \tProject Member [{0}] has TotalSalary [{1}]. member.Name,member.CalculateSalary());
29 }
30
Console.WriteLine();
32 Console.WriteLine([{0}] members will have a [{1}] on [{2}]. project.Name,project.Schedule.First().Description,153)">34 project.Schedule.First().BeginTime);
35
36 Console.ReadKey();
37 38 }
由于在业务逻辑中,ProjectManager 的项目奖金由项目的成败来决定,但是项目的成败又多少带了点运气。
1 0; } }
1 3 4 }
所以,我们可能会得到两种输出结果,成功的项目和失败的项目。
失败的项目没有项目奖金:
成功的项目拿到了项目奖金:
我们给出 UML 中的相关定义:
我们可以从不同的角度来理解和区分这三种关系:
所以,总结来说,聚合(Aggregation)是一种特殊的关联(Association),合成(Composition)是一种特殊的聚合(Aggregation)。
Association->Aggregation->Composition
参考资料
- Introduction to Object Oriented Programming Concepts (OOP) and More
- Understanding Association,Aggregation,and Composition
- UML类图基本元素符号
using System;
System.Collections.Generic;
System.Collections.ObjectModel;
System.Linq;
namespace UML
{
Program
{
[] args)
{
ProjectManager manager = );
ProjectMember member2 = );
ProjectMember member3 = );
ProjectMember member4 = );
= ScheduleItem()
{
Description = = DateTime.Now.AddDays( project.Members)
{
Console.WriteLine(
Employee
{
name)
{
ID = id;
Name = name;
}
; }
; }
CalculateSalary()
{
GetProjectBonus();
}
GetBaseSalary();
GetProjectBonus();
}
ProjectMember : Employee
{
name)
: AssignProject(Project project)
{
AssignedProject = project;
}
; }
}
ProjectManager : ProjectMember
{
GetProjectBonus()
{
;
}
}
class Schedule : List<ScheduleItem>
{
}
ScheduleItem
{
Project
{
ProjectManager _manager;
();
Schedule();
name;
_manager = manager;
}
_manager; } }
_members.AsReadOnly(); } }
_schedule; } }
; } }
members)
{
_members.AddRange(members);
_members.ForEach(m => m.AssignProject());
}
AddScheduleItem(ScheduleItem item)
{
_schedule.Add(item);
}
}
}
View Code