软件设计原则之合成复用原则

一、简介

  • (一)概念

合成复用原则,又叫组合/聚合复用原则,它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

  • (二)继承复用

通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺点:

  1. 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
  2. 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
  3. 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。

以下是继承复用类图:

软件设计原则之合成复用原则_第1张图片

 

此时A类和B类之间的耦合度很高,而且如果B类只想用A类的其中一些方法, 如果使用继承将会全部方法都继承下来了,造成冗余。在实际工作中,只有满足is - a关系的两个类才能使用继承关系。

  •  (3)合成复用

采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点:

  • 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
  • 新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
  • 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。

二、合成复用原则方式

【a】聚合:表示整体与部分的关系,表示“含有”,整体由部分组合而成,部分可以脱离整体作为一个独立的个体存在. 代表部分的对象有可能会被多个代表整体的对象所共享,而且不一定会随着某个代表整体的对象被销毁而被销毁,部分的生命周期可以超越整体。

聚合类图如下:

软件设计原则之合成复用原则_第2张图片

例如:订单与商品的关系,订单删除了,商品并不代表删除了,商品还可以被其他订单关联。示例代码:

class Order {
	private List goods;

	public Order(List goods) {
		super();
		this.goods = goods;
	}

}

class Goods {
}

 【b】组合:是一种更强的聚合,部分组成整体,而且不可分割,部分不能脱离整体而单独存在。部分和整体的生命周期是一样的,代表部分的对象会随着某个代表整体的对象被销毁而被销毁。组合类图如下:

软件设计原则之合成复用原则_第3张图片

例如:订单与订单明细的关系,订单都没了,订单明细自然不可能单独存在。示例代码:

class Order {
	private OrderDetail orderDetail = new OrderDetail();
	// 当Order对象销毁,对象orderDetail也将会同时被销毁
}

class OrderDetail {

}

【c】依赖

依赖关系的类图如下:

软件设计原则之合成复用原则_第4张图片

三、总结

到这里,我们对软件设计七大原则都进行了介绍,它们分别为单一职责原则、接口隔离原则、依赖倒置原则、里氏替换原则、迪米特法则、开闭原则、合成复用原则。

在设计软件以及写代码的时候我们都需要尽量遵循这七大原则,各个原则要求的侧重点不同,共同达成软件"高内聚,低耦合"的目标。下面阐述七大原则各自侧重点:

  1. 单一职责原则:每个类的职责要单一,不要将所有功能都交给一个类来完成;
  2. 接口隔离原则:设计接口要功能分离,尽可能让实现类只实现需要的方法;
  3. 依赖倒置原则:告诉我们需要面向接口编程,将各个类共同的部分抽成一个接口,其他类实现该接口;
  4. 里氏替换原则:尽量不要重写父类已经实现好的方法,不要破坏已设计好的继承体系,尽量通过新增方法来扩展功能;
  5. 迪米特法则:要求我们要尽量降低类之间的耦合度,只与直接朋友之间(方法形式参数、成员变量、方法返回值)产生耦合关系,不与陌生朋友(方法里定义的局部变量)产生耦合;
  6. 开闭原则:其他原则遵循的好,开闭原则自然就遵循了,开闭原则要求要对扩展开放(提供者),对修改关闭(使用者);
  7. 合成复用原则:优先考虑使用组合或者聚合(即第二点提到的合成复用原则三种方式),少用继承关系进行复用;

好了,设计原则的总结暂告一段落,还得在工作中好好使用,反复琢磨琢磨才行,任何人都不可能一下子所有原则都遵循的很好,都是反反复复修改,一步一步优化的。接下来,将会总结一些常见的设计模式。

你可能感兴趣的:(设计模式)