C#设计模式-桥接模式(Bridge Pattern)

引言

例如我有好几个项目,需要外包出去做各种类型的测试,不同的公司基础费用不同,不同的测试类型价格也是不同的。此时不同的项目选择不同的公司和不同类型的测试进行测试价格都是不同的。于是我们可以创建一个项目抽象类,一个公司抽象类,一个测试类型抽象类,然后实现各自的具体类,不同的项目使用不同的公司和测试类型,进行测试。抽象化与实现化解耦,二者可以独立变化。我们将这种通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦的类型称为桥接模式。

概念

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

结构图

桥接(Bridge)模式中的主要角色:

  • 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
  • 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
  • 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。

具体实现

以引言中的示例进行实现。一个产品需要外包出去进行测试。

涉及三个角色:产品、外包公司、测试类型

using System;

namespace Bridge
{
    class Program
    {
        static void Main(string[] args)
        {
            Company beijingCompany = new BeijingCompany();
            TestType manualTest = new ManualTest();
            Prodeuct managementProdeuct = new ManagementProdeuct(beijingCompany, manualTest);
            managementProdeuct.Run();

            Company shanghaiCompany = new ShanghaiCompany();
            TestType autoTest = new AutoTest();
            Prodeuct operationProdeuct = new ManagementProdeuct(shanghaiCompany, autoTest);
            operationProdeuct.Run();

            Console.Read();
        }
    }

    /// <summary>
    /// 软件产品,抽象类
    /// 充当抽象化角色
    /// 将抽象部分与实现部分分离,使他们都可以独立的变化
    /// </summary>
    public abstract class Prodeuct
    {
        private readonly Company _company;
        private readonly TestType _testType;

        // 使用组合,一个产品外包出去,需要一个公司进行不同测试类型的测试
        public Prodeuct(Company company, TestType testType)
        {
            this._company = company;
            this._testType = testType;
        }

        public string Name { get; set; }

        // 执行实现部分
        public void Run()
        {
            Console.WriteLine($"{this._company.Name}对产品{Name}进行{this._testType.Name},总共花费时间{this._company.BaseTime + this._testType.RunTime}。");
            Console.WriteLine("======================================================");
        }

    }

    /// <summary>
    /// 公司,对实现部分进行抽象
    /// </summary>
    public abstract class Company
    {
        public string Name { get; set; }

        public Double BaseTime { get; set; }

    }

    /// <summary>
    /// 测试类型,对实现部分进行抽象
    /// </summary>
    public abstract class TestType
    {
        public string Name { get; set; }

        public Double RunTime { get; set; }

    }

    /// <summary>
    /// 管理系统,扩展抽象化角色
    /// </summary>
    public class ManagementProdeuct : Prodeuct
    {

        public ManagementProdeuct(Company company, TestType testType) : base(company, testType)
        {
            Name = "管理系统";
        }
    }

    /// <summary>
    /// 运营系统,扩展抽象化角色
    /// </summary>
    public class OperationProdeuct : Prodeuct
    {

        public OperationProdeuct(Company company, TestType testType) : base(company, testType)
        {
            Name = "运营系统";
        }
    }

    /// <summary>
    /// 公司抽象类具体实现,具体实现化角色
    /// </summary>
    public class BeijingCompany : Company
    {
        public BeijingCompany()
        {
            Name = "北京公司";
            BaseTime = 200;
        }
    }

    /// <summary>
    /// 公司抽象类具体实现,具体实现化角色
    /// </summary>
    public class ShanghaiCompany : Company
    {
        public ShanghaiCompany()
        {
            Name = "上海公司";
            BaseTime = 100;
        }
    }

    /// <summary>
    ///测试类型抽象类具体实现,具体实现化角色
    /// </summary>
    public class ManualTest : TestType
    {
        public ManualTest()
        {
            Name = "手工测试";
            RunTime = 30;
        }
    }

    /// <summary>
    ///测试类型抽象类具体实现,具体实现化角色
    /// </summary>
    public class AutoTest : TestType
    {
        public AutoTest()
        {
            Name = "自动测试";
            RunTime = 10;
        }
    }
}

运行后结果:

北京公司对产品管理系统进行手工测试,总共花费时间230。
======================================================
上海公司对产品管理系统进行自动测试,总共花费时间110。
======================================================

适用场景

  • “抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
  • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展。
  • 对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

优缺点

优点

  • 抽象与实现分离,扩展能力强。
  • 符合开闭原则。
  • 符合合成复用原则。
  • 单一职责原则。 抽象部分专注于处理高层逻辑, 实现部分处理平台细节。

缺点

  • 由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。

与装饰器模式区别

  • 装饰器模式是为了动态地给一个对象增加功能,而桥接模式时为了让类在多个维度上自由扩展。
  • 装饰器模式的装饰者和被装饰者需要继承自同一父类,而桥接模式通常不需要;
  • 装饰器模式通常可以嵌套使用,而桥接模式不能。
(0)

相关推荐

  • 结构型模式:桥接模式

    七大结构型模式之二:桥接模式. 简介 姓名 :桥接模式 英文名 :Bridge Pattern 价值观 :解耦靠我 个人介绍 : Decouple an abstraction from its im ...

  • 行为型模式之解释器模式

    目录 定义与特点 结构与实现 模式的结构 模式的实现 应用场景 扩展:Expression 表达式树和Flee 在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性.如果将它们归纳成一 ...

  • Java描述设计模式(08):桥接模式

    Java描述设计模式(08):桥接模式 原创知了一笑2019-08-23 07:00:00 写在前面 推荐阅读: Java描述设计模式(07):适配器模式 Java描述设计模式(06):建造者模式 J ...

  • C#设计模式-装饰器模式(Decorator Pattern)

    引言 当我们完成一个软件产品开发后就需要对其进行各种测试,适配快速迭代下质量的保障.当有一个完善的产品的对象后,如果我们想要给他添加一个测试功能,那么我们可以用一个新的类去装饰它来实现对原有对象职责的 ...

  • 设计模式(7) 桥接模式

    桥接模式的概念与实现 为什么叫桥接模式 桥接模式的适用场景 继承是面向对象的三大特性之一,但很多时候使用继承的结果却不尽如人意.除了人尽皆知的紧耦合问题外,有的时候还会导致子类的快速膨胀. 设想这样一 ...

  • 桥接模式(Bridge Pattern)

    桥接模式概述 定义:将抽象部分与它的实现部分解耦,使得两者都能够独立的变化 就拿我们日常使用的蜡笔来说,蜡笔有不同的大小和颜色,所以我们往往买的蜡笔盒中会有不少的蜡笔.需要用哪个就用哪个,是不是很方便 ...

  • PHP设计模式之桥接模式

    PHP设计模式之桥接模式 桥接模式,在程序世界中,其实就是组合/聚合的代名词.为什么这么说呢?熟悉面向对象的我们都知道继承的好处,子类可以共享父类的很多属性.功能.但是,继承也会带来一个问题,那就是严 ...

  • [PHP小课堂]PHP设计模式之桥接模式

    [PHP小课堂]PHP设计模式之桥接模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • C#设计模式-组合模式(Composite Pattern)

    概念 组合是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们. 组合模式(Composite Pattern)是将对象组合成树形结构以表示'部分-整体'的层次 ...

  • 图解Java设计模式之桥接模式

    手机操作问题 传统方案解决手机操作问题 传统方案解决手机操作问题分析 桥接模式(Bridge)-基本介绍 桥接模式解决手机操作问题 桥接模式在JDBC中的源码解析 桥接模式的注意事项和细节 桥接模式其 ...

  • java设计模式7——桥接模式

    java设计模式7--桥接模式 1.桥接模式介绍 桥接模式是将抽象部分与它的实现部分分离,使他们都可以独立的变化.它是一种对象结构型模式,又称为柄体模式或接口模式. 2.解决问题 2.1.将复杂的组合 ...

  • 设计模式-结构型-桥接模式

    桥接模式(Bridge): 桥接是用于把抽象化与实现化解耦,使得两者可以独立变化. 桥接模式的角色: 1)抽象化角色(Abstraction):它是用于定义抽象接口,通常是抽象类而不是接口,其中定义了 ...