02.10 桥模式

设计模式——桥模式

需求

从现实故事说起,长虹与海尔都是大的电视机生产商,都能够生产21英寸与37英寸的电视,这个问题应该如何建模呢?下面尝试使用继承关系实现:

    // 定义一个制造商接口

    public interface IManufacturer { void ShowName(); }

    // 再定义一个电视接口

    public interface ITV { void Produce(); }

    // 定义2个电视机子类

    public class TV21inches : ITV   // 21英寸电视机

    {

        public void Produce() { Console.WriteLine("生产21英寸电视机!"); }

    }

    public class TV37inches : ITV   // 37英寸电视机

    {

        public void Produce() { Console.WriteLine("生产37英寸电视机!"); }

    }

    // 接下来只能玩万恶的多重继承了

    public class ChanghongTV21inches : TV21inches, IManufacturer    // 长虹21英寸电视机

    {

        public void ShowName() { Console.Write("长虹"); }

        public void Produce() { base.Produce(); }

    }

    public class ChanghongTV37inches : TV37inches, IManufacturer    // 长虹37英寸电视机

    {

        public void ShowName() { Console.Write("长虹"); }

        public void Produce() { base.Produce(); }

    }

    public class HaierTV21inches : TV21inches, IManufacturer    // 海尔21英寸电视机

    {

        public void ShowName() { Console.Write("海尔"); }

        public void Produce() { base.Produce(); }

    }

    public class HaierTV37inches : TV37inches, IManufacturer    // // 海尔37英寸电视机

    {

        public void ShowName() { Console.Write("海尔"); }

        public void Produce() { base.Produce(); }

    }

如果再有新的制造商或者电视规格需要加进来呢?那样继承关系真是复杂的不得了!

这样的需求上升到理论的层次,就可以总结为:系统具有多维角度的分类,每一种分类都有可能变化,却还需要可以随意组合。显然使用继承关系会使得设计非常复杂;而且使用继承关系会使得多维角度的组合在编译期就固定化。

定义

桥模式(Bridge Pattern)的GoF定义,将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化。

不好理解吧,因为我们大多习惯了继承关系里的抽象类/派生类(或者接口/实现类)的概念,而桥接模式里的“抽象”与“实现”根本不是这个意思。

这里用角色的概念来说明更好理解:当某个问题具有多维角度分类时,将其拆分为Implementor(实现者)与Abstraction(抽象者)。Implementor(实现者)提供了一些原始的功能,而Abstraction(抽象者)对实现者及其原始操作进行了更高层次的封装。

  

  

如图所示,桥模式(Bridge Pattern)由4部分组成:(1)抽象的实现者(Abstract Implementor),定义实现者的规格;(2)具体实现者(Concrete Implementor),实现抽象的实现者(Abstract Implementor)定义的那些原始功能;(3)父级抽象者(Abstraction),为实现者(Implementor)定义一个抽象的访问接口,内部维护一个对实现者(Implementor)的引用,便于调用实现者提供的那些基本操作以进行附加功能;(4)子级提炼抽象者(Refined Abstraction),实现父级抽象者,并且将抽象者的操作提炼。桥接模式(Bridge Pattern)就这样将某个问题抽象部分与该问题的实现部分相分离,使得两者都可以独立变化,并能够动态结合。

案例:电视机生产

还是回到电视机生产的问题,我们把电视机与生产商分离开来,各自单独设计。

  

    // 将电视机作为Implementor,定义一个电视机接口

    public interface ITV { void Produce(); }

    // 定义Implementor的具体类,定义2个电视机子类

    public class TV21inches : ITV   // 21英寸电视机

    {

        public void Produce() { Console.WriteLine("生产21英寸电视机!"); }

    }

    public class TV37inches : ITV   // 37英寸电视机

    {

        public void Produce() { Console.WriteLine("生产37英寸电视机!"); }

    }

    // 将生产商作为Abstraction,定义一个抽象的生产商类,在其内包裹一个电视机接口

    public abstract class Manufacturer

    {

        public Manufacturer(ITV tv) { this._TV = tv; }

        private ITV _TV;

        public virtual void ProcuedureTV() { this._TV.Produce(); }

    }

    // 在Abstraction子类实现中提炼抽象

    public class ChanghongTV : Manufacturer // 长虹生产电视机

    {

        public ChanghongTV(ITV tv) : base(tv) { }

        public override void ProcuedureTV()

        {

            Console.Write("长虹");

            base.ProcuedureTV();

        }

    }

    public class HaierTV : Manufacturer // 海尔生产电视机

    {

        public HaierTV(ITV tv) : base(tv) { }

        public override void ProcuedureTV()

        {

            Console.Write("海尔");

            base.ProcuedureTV();

        }

    }

   

    class Program

    {       

        static voidMain(string[] args)

        {

            // 客户程序

            new ChanghongTV(new TV21inches()).ProcuedureTV();

            new ChanghongTV(new TV37inches()).ProcuedureTV();

            new HaierTV(new TV21inches()).ProcuedureTV();

            new HaierTV(new TV37inches()).ProcuedureTV();

        }

    }

案例:适用于大多数需要数据库访问的界面编程

学习过三层结构后,都会觉得对中间层的理解与实现清晰多了,但是界面层的是实现比中间层复杂化、不可预测化多了。现在许多有经验的程序员,总结了大多数需要数据库访问界面的规律,设计了类似下面图中的接口与架构,希望对你有用。

  

优缺点

优点:使用桥接模式,能够比使用继承关系更灵活;它可以使抽象和实现分离,降低了耦合关系;还有其它好处,分离开的抽象与实现还允许自由组合,动态切换;减少子类个数等等。当有新的抽象或者实现需要增加时,只需要继承一个抽象或者继承一个实现即可。

缺点:(1)桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程;(2)桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。

适用场景

当系统有多维角度分类时,而每一种分类又有可能变化,可以考虑使用桥接模式。桥模式也是继承关系的一个替代方案。

补充

原文地址:https://www.cnblogs.com/sagahu/p/2715311.html