UML中关联(Association)、聚合(Aggregation)和合成(Composition)之间的区别
来源:互联网 发布:哪个淘宝课程好 编辑:程序博客网 时间:2024/05/20 11:33
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 类覆写父类的薪水计算方法。
1 public abstract class Employee 2 { 3 public Employee(int id, string name) 4 { 5 ID = id; 6 Name = name; 7 } 8 9 public int ID { get; private set; }10 public string Name { get; private set; }11 12 public double CalculateSalary()13 {14 return GetBaseSalary() + GetProjectBonus();15 }16 17 protected abstract double GetBaseSalary();18 protected abstract double GetProjectBonus();19 }20 21 public class ProjectMember : Employee22 {23 public ProjectMember(int id, string name)24 : base(id, name)25 {26 }27 28 public Project AssignedProject { get; private set; }29 30 public void AssignProject(Project project)31 {32 AssignedProject = project;33 }34 35 protected override double GetBaseSalary() { return 1000; }36 protected override double GetProjectBonus() { return 200; }37 }
根据需求 “REQ3: 一个项目内仅有一名项目成员被指派为 项目经理 负责管理项目”,可以推断出 ProjectManager 与 ProjectMember 的关系。
ProjectManager 继承自 ProjectMember。ProjectMember 类覆写父类的薪水计算方法,以实现需求 “REQ6:项目经理的项目奖金由项目的成败决定”。
1 public class ProjectManager : ProjectMember 2 { 3 public ProjectManager(int id, string name) 4 : base(id, name) 5 { 6 } 7 8 protected override double GetBaseSalary() { return 2000; } 9 10 protected override double GetProjectBonus()11 {12 return AssignedProject.IsSuccess ? 800 : 0;13 }14 }
由下面三个需求可以识别出 Project 与 ProjectMember/ProjectManager 之间的关系。
REQ1:一个 项目 内有多名 项目成员
REQ2:一名项目成员只能被指派给一个项目
REQ3:一个项目内仅有一名项目成员被指派为 项目经理 负责管理项目
Project 聚合(Aggregation)了 ProjectMember,ProjectMember 当不在该项目中时仍然可以存在,比如转去做其他项目。
Project 关联(Association)了 ProjectManager,ProjectManager 当不在该项目时,需要转换为 ProjectMember。
ProjectManager 的薪水将由所负责的项目的成败决定,会调用 Project 的状态以计算薪水。
1 public class Project 2 { 3 private ProjectManager _manager; 4 private List<ProjectMember> _members = new List<ProjectMember>(); 5 private Schedule _schedule = new Schedule(); 6 7 public Project(string name, ProjectManager manager) 8 { 9 Name = name;10 _manager = manager;11 }12 13 public string Name { get; private set; }14 public ProjectManager Manager { get { return _manager; } }15 public ReadOnlyCollection<ProjectMember> Members { get { return _members.AsReadOnly(); } }16 public Schedule Schedule { get { return _schedule; } }17 public bool IsSuccess { get { return (new Random().Next(1, 100) % 2) > 0; } }18 19 public void AssignMembers(IEnumerable<ProjectMember> members)20 {21 _members.AddRange(members);22 _members.ForEach(m => m.AssignProject(this));23 }24 25 public void AddScheduleItem(ScheduleItem item)26 {27 _schedule.Add(item);28 }29 }
根据需求 “REQ7:项目中包含 项目计划 ” 可得出 Project 与 Schedule 的关系。
根据需求 “REQ8:一个项目计划由多个 项目计划项 组成” 可得出 Schedule 与 ScheduleItem 的关系。
Project 聚合(Aggregation)了 Schedule。Schedule 由多个 ScheduleItem 组成(Composition)。
1 public class Schedule : List<ScheduleItem> 2 { 3 } 4 5 public class ScheduleItem 6 { 7 public string Description { get; set; } 8 public DateTime BeginTime { get; set; } 9 public DateTime EndTime { get; set; }10 }
由此,我们得到了满足全部需求的类图:
现在,我们可通过以上类的定义来组织业务逻辑。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ProjectManager manager = new ProjectManager(1, @"Dennis Gao"); 6 ProjectMember member2 = new ProjectMember(2, @"Super Man"); 7 ProjectMember member3 = new ProjectMember(3, @"Iron Man"); 8 ProjectMember member4 = new ProjectMember(3, @"Spider Man"); 9 10 var projectMembers = new List<ProjectMember>() { manager, member2, member3, member4 };11 12 Project project = new Project("EarnMoney", manager);13 project.AssignMembers(projectMembers);14 15 ScheduleItem item1 = new ScheduleItem()16 {17 Description = "Team Building",18 BeginTime = DateTime.Now.AddDays(5),19 EndTime = DateTime.Now.AddDays(6),20 };21 project.AddScheduleItem(item1);22 23 Console.WriteLine("Salary List of Project [{0}] Members:", project.Name);24 foreach (var member in project.Members)25 {26 Console.WriteLine(27 "\tProject Member [{0}] has TotalSalary [{1}].",28 member.Name, member.CalculateSalary());29 }30 31 Console.WriteLine();32 Console.WriteLine("[{0}] members will have a [{1}] on [{2}].",33 project.Name, project.Schedule.First().Description,34 project.Schedule.First().BeginTime);35 36 Console.ReadKey();37 }38 }
由于在业务逻辑中,ProjectManager 的项目奖金由项目的成败来决定,但是项目的成败又多少带了点运气。
1 public bool IsSuccess { get { return (new Random().Next(1, 100) % 2) > 0; } }
1 protected override double GetProjectBonus()2 {3 return AssignedProject.IsSuccess ? 800 : 0;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;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Linq;namespace UML{ class Program { static void Main(string[] args) { ProjectManager manager = new ProjectManager(1, @"Dennis Gao"); ProjectMember member2 = new ProjectMember(2, @"Super Man"); ProjectMember member3 = new ProjectMember(3, @"Iron Man"); ProjectMember member4 = new ProjectMember(3, @"Spider Man"); var projectMembers = new List<ProjectMember>() { manager, member2, member3, member4 }; Project project = new Project("EarnMoney", manager); project.AssignMembers(projectMembers); ScheduleItem item1 = new ScheduleItem() { Description = "Team Building", BeginTime = DateTime.Now.AddDays(5), EndTime = DateTime.Now.AddDays(6), }; project.AddScheduleItem(item1); Console.WriteLine("Salary List of Project [{0}] Members:", project.Name); foreach (var member in project.Members) { Console.WriteLine( "\tProject Member [{0}] has TotalSalary [{1}].", member.Name, member.CalculateSalary()); } Console.WriteLine(); Console.WriteLine("[{0}] members will have a [{1}] on [{2}].", project.Name, project.Schedule.First().Description, project.Schedule.First().BeginTime); Console.ReadKey(); } } public abstract class Employee { public Employee(int id, string name) { ID = id; Name = name; } public int ID { get; private set; } public string Name { get; private set; } public double CalculateSalary() { return GetBaseSalary() + GetProjectBonus(); } protected abstract double GetBaseSalary(); protected abstract double GetProjectBonus(); } public class ProjectMember : Employee { public ProjectMember(int id, string name) : base(id, name) { } public Project AssignedProject { get; private set; } public void AssignProject(Project project) { AssignedProject = project; } protected override double GetBaseSalary() { return 1000; } protected override double GetProjectBonus() { return 200; } } public class ProjectManager : ProjectMember { public ProjectManager(int id, string name) : base(id, name) { } protected override double GetBaseSalary() { return 2000; } protected override double GetProjectBonus() { return AssignedProject.IsSuccess ? 800 : 0; } } public class Schedule : List<ScheduleItem> { } public class ScheduleItem { public string Description { get; set; } public DateTime BeginTime { get; set; } public DateTime EndTime { get; set; } } public class Project { private ProjectManager _manager; private List<ProjectMember> _members = new List<ProjectMember>(); private Schedule _schedule = new Schedule(); public Project(string name, ProjectManager manager) { Name = name; _manager = manager; } public string Name { get; private set; } public ProjectManager Manager { get { return _manager; } } public ReadOnlyCollection<ProjectMember> Members { get { return _members.AsReadOnly(); } } public Schedule Schedule { get { return _schedule; } } public bool IsSuccess { get { return (new Random().Next(1, 100) % 2) > 0; } } public void AssignMembers(IEnumerable<ProjectMember> members) { _members.AddRange(members); _members.ForEach(m => m.AssignProject(this)); } public void AddScheduleItem(ScheduleItem item) { _schedule.Add(item); } }}
- UML中关联(Association)、聚合(Aggregation)和合成(Composition)之间的区别
- UML中关联(Association)、聚合(Aggregation)和合成(Composition)之间的区别
- UML中类之间的几种关系,关联(association),聚合(Aggregation),组合(Composition)
- UML的关联(Association), 聚合(Aggregation), 组合(Composition)区别
- UML中Association(关联), Aggregation(聚合), Composition(组合)和Dependency(依赖)辨析
- UML中Association(关联), Aggregation(聚合), Composition(组合)和Dependency(依赖)辨析
- 面向对象编程中Association、Aggregation和Composition的区别
- 合成/聚合复用原则 (Composition/Aggregation Principle, CARP)
- 聚合(Aggregation)和组合(Composition)的区别
- 聚合(Aggregation)和组合(Composition)的区别
- 在UML 中,聚合(aggregation)和组合(composition)有什么区别?
- 关联(association)、依赖(dependency)、聚合(Aggregation,也有的称聚集)、组合(Composition)、泛化(generalization,也有的称继承)、实现(R
- association中aggregation和composition说明
- association中aggregation和composition说明
- association中aggregation和composition说明
- CARP(Composition/Aggregation Reuse Principle)合成/聚合复用原则
- 聚合Aggregation与合成Composition
- [转]association,aggregation, composition 区别
- expire_logs_day binlog自动过期清理binlog
- WebAPI的一种单元测试方案
- 欢迎使用CSDN-markdown编辑器
- 多线程 - 阻塞栈blockingDeque
- Android实现滑动的几种方法
- UML中关联(Association)、聚合(Aggregation)和合成(Composition)之间的区别
- 角色类设计2
- Python 获取对象信息
- 几种高速缓存算法
- map hash_map unordered_map 性能测试
- iOS开发经验:高德地图折线或者图形等覆盖物的适配显示
- 2年经验须知
- union和union all及区别
- make execvp /bin/bash argument list too long