合成复用原则
合成复用原则:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过委派达到复用已有功能的目的。
简而言之,要尽量使用对象合成/聚合,尽量不要使用继承。
区分"has-A"和"is-A"是严格的分类学意义定义,意思是一个类是另一个类的一种。而"has-A"则不同,它表示某一角色具有某一项责任。导致错误的使用继承而不是合成/聚合的一个常见原因是错误地将"has-A"当作"is-A"。
面向对象设计原则中继承的限制:对象的继承关系在编译时就已经确定好了,所以无法在运行时改变从父类继承的实现,子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其它更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
合成和复用都是关联的特殊种类,复用表示一种"拥有"关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。
合成则是一种强的"拥有"关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。比如:复用体现在一只大雁和一群大雁,合成体现在大雁与翅膀。
盲目使用继承会影响程序的扩展和修改,本质原因是继承是一种强耦合结构,父类变,子类就要变。使用继承时要在"is-a"关系时再考虑使用,而不是任何时候都去使用。
合成复用原则分析
在面向对象设计中,可以通过两种基本方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承。
继承复用:实现简单,易于拓展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。("白箱复用")。(子类与父类) 使用继承时,需要严格遵守里氏替换原则。要避免在程序系统设计中出现一个类的继承层次超过3次。
合成复用:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行。("黑箱复用")(个体与整体)。
合成复用原则实例
namespace 合成复用原则
{
//合成复用原则
//人和嘴巴
public class Head
{
private Mouth mouth;
public Head()
{
mouth = new Mouth();
}
}
public class Mouth
{
}
//汽车和引擎
public class Car
{
private Engine engine;
public Car(Engine engine)
{
this.engine = engine;
}
public void SetEngine(Engine engine)
{
this.engine=engine;
}
}
public class Engine
{
}
//操作系统和手机
public class IOS
{
}
public class Iphone5
{
private IOS iOS;
public Iphone5(IOS iOS)
{
this.iOS = iOS;
}
public void CreateIphone()
{
Console.WriteLine("我有一台Ipone5,上面搭载有IOS操作系统");
}
}
internal class Program
{
static void Main(string[] args)
{
Iphone5 iphone5 = new Iphone5(new IOS());
iphone5.CreateIphone();
Console.Read();
}
}
}