【设计模式】UML类图 C#的代码实现
C#学习设计模式之前,必看uml类图的C#代码写法
面向对象的特点是可维护、可复用、可扩展、灵活性好,它真正强大的地方在于:随着业务变得越来越复杂,面向对象依然能够使得程序结构良好,而面向过程却会导致程序越来越臃肿。
让面向对象保持结构良好的秘诀就是 设计模式。
关联、聚合、组合的区别
关联、聚合、组合只能配合语义,结合上下文才能够判断出来,而只给出一段代码让我们判断是关联,聚合,还是组合关系,则是无法判断的。
关联:被关联的对象是可以共享的,可以被多个对象同时关联,生命周期也没有直接关系。
聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。。聚合是整体和个体之间的关系,整体和局部的生命周期可以不一样。
组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。
关联(Assocition)关系是类与类之间最常见的一种关系,它是一种结构化的关系,表示一类对象与另一类对象之间有联系,如汽车和轮胎、师傅和徒弟、班级和学生等。在UML类图中,用实线连接有关联关系的对象所对应的类,在Java中通常将一个类的对象作为另一个类的成员变量。关联关系分单向关联、双向关联、自关联,逐一看一下。
1、单向关联关系
单向关联指的是关联只有一个方向,比如顾客(Customer)拥有地址(Address),其Java实现为:
public class Address
{
}
public class Customer
{
private Address address;//多一个执行指针就是 关联
}
UML的画法为:
为什么依赖比关联的耦合度低?
依赖对应对象方法的局部变量,关联对应对象的成员变量。
成员变量和对象具有相同的生命周期,即类A一直和类B存在关联关系
局部变量只有在方法被调用时,类A才会和类B存在依赖关系
因此从关系存在的时间长短可以推断出依赖比关联耦合度低
2、双向关联关系
默认情况下的关联都是双向的,比如顾客(Customer)购买商品(Product),反之,卖出去的商品总是与某个顾客与之相关联,这就是双向关联。Java类的写法为:
public class Product
{
private Customer customer;
}
public class Customer
{
private Product[] product;
}
对应的UML类图应当是:
3、自关联关系
自关联,指的就是对象中的属性为对象本身,这在链表中非常常见,单向链表Node中会维护一个它的前驱Node,双向链表Node中会维护一个它的前驱Node和一个它的后继Node。就以单向链表为例,它的Java写法为:
public class Node
{
private Node nextNode;
}
对应的UML类图应当是:
对于的设计模式
聚合关系
组合关系要求有统一生存期,组合和聚合代码上表现为生存期不一样。
聚合(Aggregation)关系表示整体与部分的关系。在聚合关系中,成员对象是整体的一部分,但是成员对象可以脱离整体对象独立存在。在UML中,聚合关系用带空心菱形的直线表示,如汽车(Car)与引擎(Engine)、轮胎(Wheel)、车灯(Light),Java表示为:
public class Engine
{
}
public class Wheel
{
}
public class Light
{
}
public class Car
{
private Engine engine;
private Light light;
private Wheel wheel;
public Car(Engine engine, Light light, Wheel wheel)
{
super();
this.engine = engine;
this.light = light;
this.wheel = wheel;
}
public void drive()
{
}
}
对应的UML类图为:
代码实现聚合关系,成员对象通常以构造方法、Setter方法的方式注入到整体对象之中。
组合关系
组合(Composition)关系也表示的是一种整体和部分的关系,但是在组合关系中整体对象可以控制成员对象的生命周期,一旦整体对象不存在,成员对象也不存在,整体对象和成员对象之间具有同生共死的关系。在UML中组合关系用带实心菱形的直线表示。
组合关系要求有统一生存期,组合和聚合代码上表现为生存期不一样。
比如人的头(Head)和嘴巴(Mouth)、鼻子(Nose),嘴巴和鼻子是头的组成部分之一,一旦头没了,嘴巴也没了,因此头和嘴巴、鼻子是组合关系,Java表示为:
public class Mouth
{
}
public class Nose
{
}
public class Head
{
private Mouth mouth;
private Nose nose;
public Head()
{
mouth = new Mouth();
nose = new Nose();
}
public void shake()
{
}
}
其UML的表示方法为:
代码实现组合关系,通常在整体类的构造方法中直接实例化成员类,这是因为组合关系的整体和部分是共生关系,如果通过外部注入,那么即使整体不存在,那么部分还是存在的,这就相当于变成了一种聚合关系了。
依赖关系
依赖(Dependency)关系是一种使用关系,特定事物的改变有可能会影响到使用该事物的其他事物,在需要表示一个事物使用另一个事物时使用依赖关系,大多数情况下依赖关系体现在某个类的方法使用另一个类的对象作为参数。在UML中,依赖关系用带箭头的虚线表示,由依赖的一方指向被依赖的一方。
依赖关系比较好区分,它是耦合度最弱的一种,在java中表现为局域变量、方法的形参,或者对静态方法的调用,如下面的例子:Driver类依赖于Car类,Driver的三个方法分别演示了依赖关系的三种不同形式。
比如,驾驶员(Driver)开车,Driver类的drive()方法将车(Car)的对象作为一个参数传递,以便在drive()方法中能够调用car的move()方法,且驾驶员的drive()方法依赖车的move()方法,因此也可以说Driver依赖Car,Java代码为:
class Driver { //通过形参方式发生依赖关系 public void drive1(Car car) { car.run(); } //通过局部变量发生依赖关系 public void drive2() { Car car = new Car(); car.run(); } //通过静态变量发生依赖关系 public void drive3() { Car.run(); } }
其UML的画法为:
依赖关系通常通过三种方式来实现:
- 将一个类的对象作为另一个类中方法的参数
- 在一个类的方法中将另一个类的对象作为其对象的局部变量
- 在一个类的方法中调用另一个类的静态方法