设计模式之-桥接模式

定义:

桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们均可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。git

桥接模式参与者

  • Abstraction:抽象。
  • RefinedAbstraction:被提炼的抽象。
  • Implementor:实现。
  • ConcreteImplementorA:具体实现。
  • ConcreteImplementorB:具体实现。

桥接模式基本代码

Implementor类:github

namespace BridgePattern.BasicStructure
{
    abstract class Implementor
    {
        public abstract void Operation();
    }
}

ConcreteImplementorA类:编程

namespace BridgePattern.BasicStructure
{
    class ConcreteImplementorA : Implementor
    {
        public override void Operation()
        {
            Console.WriteLine("具体实现A的方法执行");
        }
    }
}

ConcreteImplementorB类:ide

namespace BridgePattern.BasicStructure
{
    class ConcreteImplementorB : Implementor
    {
        public override void Operation()
        {
            Console.WriteLine("具体实现B的方法执行");
        }
    }
}

Abstraction类:this

namespace BridgePattern.BasicStructure
{
    abstract class Abstraction
    {
        protected Implementor implementor;

        public void SetImplementor(Implementor implementor)
        {
            this.implementor = implementor;
        }
        public virtual void Operation()
        {
            implementor.Operation();
        }
    }
}

RefinedAbstraction类:spa

namespace BridgePattern.BasicStructure
{
    class RefinedAbstraction : Abstraction
    {
        public override void Operation()
        {
            implementor.Operation();
        }
    }
}

客户端调用代码:设计

    static void Main(string[] args)
    {
        try
        {
            {//BasicStructure
                Abstraction abstraction = new RefinedAbstraction();
                abstraction.SetImplementor(new ConcreteImplementorA());
                abstraction.Operation();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

结果以下:3d

用桥接模式实现手机品牌与手机软件之间耦合带来的问题

场景模拟:现有多种手机品牌,每种手机品牌的手机又都有某一些软件,好比:游戏软件,通信录,相机,听歌......code

好比咱们有M和N两种手机品牌,M手机和N手机都有X和Y两种软件。对象

咱们能够这样设计:

  • 定义一个品牌抽象类。
  • 分别定义继承自品牌抽象类的M,N品牌类。
  • 分别定义继承自M品牌类的X软件类和Y软件类,分别定义继承自N品牌类的X软件类和Y软件类。

咱们还能够这样设计:

  • 定义一个软件抽象类。
  • 分别定义继承自软件抽象类的X,Y软件类。
  • 分别定义继承自X软件类的M品牌类和N品牌类,分别定义继承自Y软件类的M品牌类和N品牌类。

以上两种方案均可以实现,但咱们仔细分析下,若是咱们再添加一个手机品牌呢和再添加一个软件呢?

若是是第一个方案设计的话,再添加一个软件的话,势必会修改原来的代码。

若是是第二个方案设计的话,再添加一个手机品牌的话,也会修改原来的代码。

并且无论哪一种方案,当扩展一个新的品牌或软件时,新增的类也很是的多,当时间愈来愈久,软件和品牌愈来愈多时,你会发现你会崩溃的。

咱们用M表明手机品牌,用N表明软件,这时候类的递增规律是呈(M*N+M)或(M*N+N)递增的。

接下来咱们就用桥接模式使得它呈M+N模式递增

HandsetSoft(手机软件)类——Implementor类

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手机软件抽象类
    /// </summary>
    abstract class HandsetSoft
    {
        public abstract void Run(string name);
    }
}

HandsetGame(手机游戏)类——ConcreteImplementorA类

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手机游戏类
    /// </summary>
    class HandsetGame : HandsetSoft
    {
        public override void Run(string name)
        {
            Console.WriteLine($"{name}手机正在运行手机游戏");
        }
    }
}

HandsetAddressList(手机通信录)类——ConcreteImplementorB类

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手机通信录类
    /// </summary>
    class HandsetAddressList : HandsetSoft
    {
        public override void Run(string name)
        {
            Console.WriteLine($"{name}手机正在运行手机通信录");
        }
    }
}

HandsetBrand(手机品牌)类——Abstraction类

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手机品牌类抽象类
    /// </summary>
    abstract class HandsetBrand
    {
        protected HandsetSoft handsetSoft;

        public void SetHandsetBrand(HandsetSoft handsetSoft)
        {
            this.handsetSoft = handsetSoft;
        }
        public virtual void Run(string name)
        {
            handsetSoft.Run(name);
        }
    }
}

Huawei(华为)类——RefinedAbstraction类

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 华为手机
    /// </summary>
    class Huawei : HandsetBrand
    {
        public override void Run(string name)
        {
            handsetSoft.Run(name);
        }
    }
}

Xiaomi(小米)类——RefinedAbstraction类

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 小米手机
    /// </summary>
    class Xiaomi : HandsetBrand
    {
        public override void Run(string name)
        {
            handsetSoft.Run(name);
        }
    }
}

客户端调用代码:

    static void Main(string[] args)
    {
        try
        {
            {//SituationSimulation
                HandsetBrand huawei = new Huawei();
                huawei.SetHandsetBrand(new HandsetGame());
                huawei.Run("华为");

                HandsetBrand xiaomi = new Xiaomi();
                xiaomi.SetHandsetBrand(new HandsetGame());
                xiaomi.Run("小米");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

结果以下:

这样就能够实现(M+N)类递增模式了,还很好的知足了"开闭原则"。

优势:

  • 分离抽象接口及其实现部分。
  • 桥接模式有时相似于多继承方案,可是多继承方案违背了类的单一职责原则(即一个类只有一个变化的缘由),复用性比较差,并且多继承结构中类的个数很是庞大,桥接模式是比多继承方案更好的解决方法。
  • 桥接模式提升了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不须要修改原有系统。
  • 实现细节对客户透明,能够对用户隐藏实现细节。

缺点:

  • 桥接模式的引入会增长系统的理解与设计难度,因为聚合关联关系创建在抽象层,要求开发者针对抽象进行设计与编程。 - 桥接模式要求正确识别出系统中两个独立变化的维度,所以其使用范围具备必定的局限性。

适用环境:

在如下状况下可使用桥接模式:

  • 若是一个系统须要在构件的抽象化角色和具体化角色之间增长更多的灵活性,避免在两个层次之间创建静态的继承联系,经过桥接模式可使它们在抽象层创建一个关联关系。
  • 抽象化角色和实现化角色能够以继承的方式独立扩展而互不影响,在程序运行时能够动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统须要对抽象化角色和实现化角色进行动态耦合。
  • 一个类存在两个独立变化的维度,且这两个维度都须要进行扩展。
  • 虽然在系统中使用继承是没有问题的,可是因为抽象化角色和具体化角色须要独立变化,设计要求须要独立管理这二者。
  • 对于那些不但愿使用继承或由于多层次继承致使系统类的个数急剧增长的系统,桥接模式尤其适用。

总结:

  • 桥接模式将抽象部分与它的实现部分分离,使它们均可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
  • 桥接模式包含以下四个角色:抽象类中定义了一个实现类接口类型的对象并能够维护该对象;扩充抽象类扩充由抽象类定义的接口,它实现了在抽象类中定义的抽象业务方法,在扩充抽象类中能够调用在实现类接口中定义的业务方法;实现类接口定义了实现类的接口,实现类接口仅提供基本操做,而抽象类定义的接口可能会作更多更复杂的操做;具体实现类实现了实现类接口而且具体实现它,在不一样的具体实现类中提供基本操做的不一样实现,在程序运行时,具体实现类对象将替换其父类对象,提供给客户端具体的业务操做方法。
  • 在桥接模式中,抽象化(Abstraction)与实现化(Implementation)脱耦,它们能够沿着各自的维度独立变化。
  • 桥接模式的主要优势是分离抽象接口及其实现部分,是比多继承方案更好的解决方法,桥接模式还提升了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不须要修改原有系统,实现细节对客户透明,能够对用户隐藏实现细节;其主要缺点是增长系统的理解与设计难度,且识别出系统中两个独立变化的维度并非一件容易的事情。
  • 桥接模式适用状况包括:须要在构件的抽象化角色和具体化角色之间增长更多的灵活性,避免在两个层次之间创建静态的继承联系;抽象化角色和实现化角色能够以继承的方式独立扩展而互不影响;一个类存在两个独立变化的维度,且这两个维度都须要进行扩展;设计要求须要独立管理抽象化角色和具体化角色;不但愿使用继承或由于多层次继承致使系统类的个数急剧增长的系统。

 

源代码地址:https://github.com/houzhenhuang/DesignPattern

相关文章
相关标签/搜索