假想场景:hp和apple是全球知名的电脑生产厂家,起初他们各自的电脑操作系统分别是linux和macintosh,microsoft是软件行业的龙头。为了吸引更多客户购买电脑,hp和apple请ms为他们开发两款最常用的软件,办公软件和及时通讯工具。ms结了订单后,分别为hp和apple开发了office和msn。随着微软windows操作系统的大面积普及,hp的linux和apple的mac使用的人越来越少。最后hp和apple不得不在自己的硬件平台上也支持windows操作系统,同样,他们不得不请ms帮助开发windows上的office和msn。这样,为了兼容三种操作系统,ms开发出了三种对应的office和msn。随着微软.net技术的普遍应用,hp和apple又不得不请ms为他们在windows平台上开发visual studio来提升对开发人员的吸引力。
上面的场景和“
简单工厂、工厂方法和抽象工厂模式”那一篇非常相似,不同的地方是电脑多了一种操作系统,软件也相应的多了一种。这里我们可以抽象出另外一种设计模式:桥接模式,即将抽象部分和实现部分分离,使他们可以独立地变化。什么叫“抽象部分和实现部分分离”呢?就假想场景而言,就是让电脑既可以按照操作系统来分类,也可以按照应用软件功能来分类(操作系统是特殊的软件,这里把它单独当作区分电脑的一种分类方式)。更通俗的理解就是“实现系统可能又多种角度分类,每一种分类都可能变化,把这种多角度分离出来让他们独立变化,减少他们之间的耦合”。Code is cheap。看代码了:
Code
using System;
/* 按照软件功能分类 */
/// <summary>
/// 应用程序抽象类
/// </summary>
abstract class Application
{
public abstract void Run();
}
/*office,msn,vs具体类*/
class Office : Application
{
public override void Run()
{
Console.Write("Run Office");
}
}
class Msn : Application
{
public override void Run()
{
Console.Write("Run Msn");
}
}
class VisualStudio : Application
{
public override void Run()
{
Console.Write("Run VS");
}
}
/* 按照操作系统分类 */
abstract class Os
{
protected Application software;
public void SetApplication(Application app)//电脑需要安装应用程序
{
this.software = app;
}
public abstract void Run(); //电脑运行
}
/*windows,linuxs,mac具体类*/
class MsWindows : Os
{
public override void Run()
{
software.Run();
}
}
class HpLinux : Os
{
public override void Run()
{
software.Run();
}
}
class AppleMac : Os
{
public override void Run()
{
software.Run();
}
/// <summary>
/// 客户端调用
/// </summary>
static void Main(string[] args)
{
Os myOs;
myOs = new MsWindows();
myOs.SetApplication(new Office()); //安装office
myOs.Run();
myOs.SetApplication(new Msn()); //安装msn
myOs.Run();
myOs.SetApplication(new VisualStudio()); //安装vs
myOs.Run();
Console.Read();
}
} 上面的代码是一种松耦合的程序,它遵循了合成/聚合复用原则。所谓合成,是一种强的“拥有”关系,体现了严格的整体与部分的关系,部分和整体的生命周期一样;所谓聚合,是一种弱的“拥有”关系,体现的是a对象可以包含b对象,但b对象不是a对象的一部分。举例来说,翅膀和大雁是部分与整体的关系,且它们的生命周期相同,是合成关系;而大雁和雁群是聚合关系,因为每只大雁都是属于一个雁群,一个雁群可以又多只大雁。相应的,我们的代码部分,应用程序application和操作系统os就是聚合关系。
合成/聚合复用原则的好处是:”有助于保持每个类被封装,并被集中在单个任务中,这样类和类的继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。“