第十三课 桥接模式
概述:
有没有碰到过这样的情况。在系统中,有些复杂逻辑,它具有两个以上维度的变化,这样的话,就无法遵循类的单一原则,提高了关系复杂性,难于维护。那么这种情况下,应当怎么来将他的2个变化点剥离呢?就是桥接模式了。
这里使用一个日志记录模块的设计来进行说明。
需求如下:
首先,我要实现一个日志记录功能,要求能够扩展多种记录方式,例如:数据库,文本,xml 等。然后要支持 windows 平台,又要支持linux平台。 那么我们怎么来设计这个模块的结构呢?
1. 定义基类Log
2. 对应数据库模式的 DBLog
3. 对应文本模式的 TextLog
4. 对应XML模式的 XMLLog
然后呢,我们好需要他支持多个平台。怎么办?各个模式下面在扩展平台吗?如下图。
显然这样是不好的。为什么这么说呢,首先这Log上面有两个变化点,日志模式,和操作平台。这显然不符合类的单一职责原则,会造成复杂的变化,难于维护和扩展。那么怎么解决呢。一直看我这一设计模式系列的人可能会很快想到适配器模式吧。把平台这里构件化,使用适配器的方式可以解决问题吧。没错,就是这个思路,但是结构怎么设计呢?如何将适配器模式结合进来呢。方法是,提供一个平行逻辑,如下图所示。
1. 基于操作系统构件的基类 Slog
2. Windows系统的 WLog
3. Linux 系统的 LLog
4. Unix系统的 ULog
然后将起作为Log的构件引入。形成如下关系。
这样就将模式变化和平台变化分离出来了,那么如何结合起来呢?使用类似适配器模式那样,在Log中定义一个Slog的对象,在不同实现的时候,使用Slog对象来执行操作即可。下面使用代码实现吧。
C#:代码
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Log logger = new TextLog();
logger.Implementor = new WLog();
logger.Write("Log Test");
Console.Read();
}
}
public abstract class Log
{
protected SLog implementor;
public SLog Implementor
{
set { implementor = value; }
}
public virtual void Write(string log)
{
implementor.Execute(log);
}
}
public class DBLog : Log
{
public override void Write(string log)
{
implementor.Execute(log);
}
}
public class TextLog : Log
{
public override void Write(string log)
{
implementor.Execute(log);
}
}
public class XMLLog : Log
{
public override void Write(string log)
{
implementor.Execute(log);
}
}
public abstract class SLog
{
public abstract void Execute(string msg);
}
public class WLog : SLog
{
public override void Execute(string msg)
{
Console.WriteLine("Windows下记录:"+msg);
}
}
public class LLog : SLog
{
public override void Execute(string msg)
{
Console.WriteLine("Linux下记录:" + msg);
}
}
public class ULog : SLog
{
public override void Execute(string msg)
{
Console.WriteLine("Unix下记录:" + msg);
}
}
}
看明白了吗,这里分别用了两个线路封装两种变化点,通过类似适配器方式,进行了结合使用。相当于将两部分桥接起来了,这也就是桥接模式了。
可能有人会说,这样客户端调用的时候耦合性就高了,需要设置相匹配的平台对象。但是,忘了吗,用工厂里面提到的映射方法可以吗?嘿嘿,自己试着通过配置来初始化Log吧。
总结:
1. 当要设计一个类对象,但是这个类对象有多个变化点时,可以考虑通过桥接分离变化。
2. 如果两个变化点变化概率很小,就需要你好好衡量是否需要使用桥梁模式。桥梁模式相对复杂,没有必要的话不推荐使用。
3. 桥梁模式会产生类对象间耦合性,但是可以考虑使用其他设计模式来解决耦合问题,例如通过抽象工厂结合反射来获得对象。
以上
作者:王文斌
转载请注明出处