目录:设计模式之小试牛刀
源码路径:Github-Design Pattern


定义:(Bridge Pattern)

将抽象和实现解耦,使得两者可以独立地变化。

类图:

启示:

一个产品的研发,流程主要包括需求分析、产品设计、制定计划、任务安排、进度把控、产品发布、后期运维。

按照我们一般的设计思路,我们可能会如下设计:

定义一个抽象的ProjectManager类,用来定义项目的开发流程,不同的项目通过继承来实现具体的流程。每增加新的项目,就只需要继承该类重新实现即可。但这仅适用于某个单一角色对产品的管理。

我们知道一个IT公司的组织架构一般由CEO、产品经理、项目经理和员工组成。CEO负责整个公司运行项目的整体把控,产品经理负责公司的某一条产品线,项目经理则负责产品线中的某个项目的开发管理,而员工就是负责项目的开发工作。

作为一名项目经理,职责可能主要是制定开发计划和任务分配,并把控进度。但若作为一名产品经理,职责可能就需要额外负责需求分析、产品设计的工作,职位越高,责任越大嘛。

按照之前的设计,我们就需要针对同一个项目不同的角色分别提供不同的实现,这显然是不合理的。且每个角色都被赋予了同样的流程管理功能,这也是不符合现实场景的。那如何做到项目管理根据不同角色和不同项目灵活变化呢?要想做到这一点,我们就必须将之前项目管理和项目的紧耦合关系松松绑。而如何松绑呢,咱们借助『桥接模式』。

Talk is cheap, show you the code!

代码:

从面向对象的角度,我们可以抽象出经理和项目两个对象,将这些工作流程抽象为具体的行为方法。

那这些行为方法的附属该如何设置呢?经理作为项目的主要把控者,以上的工作是经理的职责所在。但是,这些工作又都是基于项目的,也就是说我们也可以将这些工作看成是项目本身的行为。你可能会按以人为本的思想,将这些行为方法定义到经理的角色里。但这样就会有一个问题,假设项目经理在项目尚未结束的时候因为某些因素辞职了或人事变动调离了,那之前的项目的工作安排就不可控了,这是不允许的。所以最好还是把这些行为方法定义到具体的项目中去。

public abstract class Project
{public string ProjectName { get; set; }protected Project(string projectName){ProjectName = projectName;}/// <summary>/// 需求分析/// </summary>public abstract void AnalyzeRequirement();/// <summary>/// 产品设计/// </summary>public abstract void DesignProduct();/// <summary>/// 制定计划/// </summary>public abstract void MakePlan();/// <summary>/// 任务分解/// </summary>public abstract void ScheduleTask();/// <summary>/// 进度把控/// </summary>public abstract void ControlProcess();/// <summary>/// 产品发布/// </summary>public abstract void ReleaseProduct();/// <summary>/// 后期运维/// </summary>public abstract void MaintainProduct();
}

那如何做到不同的角色赋予不同的项目管理职责呢?我们可以将职责最少的角色抽象出来。比如我们可以将项目经理制定产品计划、任务分配和进度把控抽离出来。

public abstract class Manager
{protected Project CurrentProject { get; }protected Manager(Project currentProject){CurrentProject = currentProject;}/// <summary>/// 制定计划/// </summary>public abstract void SchedulePlan();/// <summary>/// 任务分配/// </summary>public abstract void AssignTasks();/// <summary>/// 进度把控/// </summary>public abstract void ControlProcess();/// <summary>/// 项目管理/// </summary>public virtual void ManageProject(){SchedulePlan();AssignTasks();ControlProcess();}
}

然后项目经理和产品经理继承实现基本职责,根据需要动态添加额外的职责。

我们看看项目经理的具体实现:

/// <summary>
/// 项目经理
/// </summary>
public class ProjectManager : Manager
{public ProjectManager(Project currentProject) : base(currentProject){}public override void SchedulePlan(){base.CurrentProject.MakePlan();}public override void AssignTasks(){base.CurrentProject.ScheduleTask();}public override void ControlProcess(){base.CurrentProject.ControlProcess();}public override void ManageProject(){Console.WriteLine($"项目经理负责【{base.CurrentProject.ProjectName}】:");base.ManageProject();}}

再看看产品经理的实现:

/// <summary>
/// 产品经理
/// </summary>
public class ProductManger : Manager
{public ProductManger(Project currentProject) : base(currentProject){}public override void SchedulePlan(){base.CurrentProject.MakePlan();}public override void AssignTasks(){base.CurrentProject.ScheduleTask();}public override void ControlProcess(){base.CurrentProject.ControlProcess();}public void AnalyseRequirement(){base.CurrentProject.AnalyzeRequirement();}public void DesignProduct(){base.CurrentProject.DesignProduct();}public override void ManageProject(){AnalyseRequirement();DesignProduct();base.ManageProject();}public override void ManageProject(){Console.WriteLine($"产品经理负责【{base.CurrentProject.ProjectName}】:");AnalyseRequirement();DesignProduct();base.ManageProject();}}

可以看到我们为产品经理额外添加了需求分析和产品设计的职责。

下面我们看看最终的场景类:

Project webProject = new WebProject("Web项目");
Manager projectManager = new ProjectManager(webProject);
Manager productManager = new ProductManger(webProject);projectManager.ManageProject();
productManager.ManageProject();Console.ReadLine();

总结:

通过上面的demo,我们解决了之前通过继承设计的弊端,即项目管理和项目不能灵活适应变化。通过引入桥接模式,将项目管理和项目解耦,我们实现了项目管理(抽象)和项目(实现)的分离。桥接模式的意图还是对变化的封装,尽量把可能变化的因素封装到最细、最小的逻辑单元中,避免风险扩散。而这也正是桥接模式的精髓所在。

优缺点:

桥接模式将抽象和实现分离,实现可以不受抽象的约束,不用再绑定在一个固定的抽象层次上;抽象和实现均可自由扩展。

应用场景:

  1. 不希望或不适用使用继承的场景
  2. 接口或抽象类不稳定的场景
  3. 重用性要求较高的场景
  4. 解决多层继承

牵线搭桥,『桥接模式』相关推荐

  1. 创建相似对象,就交给『工厂模式』吧

    源码: 源代码C# 系列导航: 目录 定义(Factory Pattern): 用来创建目标对象的类,将相似对象的创建工作统一到一个类来完成. 一.简单工厂模式: 代码: /// <summar ...

  2. 这一次数据说了算,『访问者模式』

    定义:(Visitor Pattern) 封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作. 换句话说: 访问者模式赋予了[数据]的选择权. 一般 ...

  3. 『设计模式』大话西游的移魂大法竟移出来了桥接模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 大话西游里有那么一幕,牛魔王的妹妹使用移魂大法,使几个人的灵魂交换.我们考虑一个问题,一个哲学问题,到底他们时灵魂发生了转移,还是肉体发生了转移.到 ...

  4. MyZip pro专业极速解压放弃了Mac上落后的拖拽解压压缩模式,采用『右键菜单』进行压缩、解压,极大的符合了用户最初的使用习惯。

    1.右键压缩解压 首先,MyZip放弃了Mac上落后的拖拽解压压缩模式,采用『右键菜单』进行压缩.解压,极大的符合了用户最初的使用习惯. 2.多线程极速压缩 很多时候,我们在Mac上压缩总感觉很慢,7 ...

  5. NAT模式 桥接模式bridge原理理解

    桥接场景 无论现在的各种容器,还是我们之前常用的虚拟机,为了与局域网内其他IP通讯通常需要用到『桥接』. Bridge桥接方式 Bridge 将虚拟机桥接到host机器的网卡上,guest和host机 ...

  6. 『高级篇』docker之APIGateway(17)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『高级篇』docker之APIGateway(17) 这次说最后一个模块APIGateway,他的功能就是将我们客户端的请求统 ...

  7. 『高级篇』docker之DockerSwarm的集群环境搭建(28)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『高级篇』docker之DockerSwarm的集群环境搭建(28) 上次了解了docker Swarm,这次一起动手操作,搭 ...

  8. 2017-2018-2 165X 『Java程序设计』课程 助教总结

    2017-2018-2 165X 『Java程序设计』课程 助教总结 本学期完成的助教工作主要包括: 编写300道左右测试题,用于蓝墨云课下测试: 发布博客三篇:<2017-2018-2 165 ...

  9. 13 个适合『中级开发者』练手的项目

    本文整理自『机器之心』 编辑 / sitin 本文将列出十三个适合中级 Python 开发人员练手的项目. Web 项目设计 1.内容聚合器(Content Aggregator) 1. 技术细节 该 ...

最新文章

  1. php如何解决中文乱码问题?
  2. HTML5 新增内容
  3. 为什么 SAP Spartacus 4.0 源代码版本读取不到 CX_BASE_URL 环境变量的值?
  4. 自定义控件android特效,Android自定义控件eBook实现翻书效果实例详解
  5. anaconda python目录_Python Anaconda2 (64-bit) 安装后启动jupyter-notebook默认目录更改
  6. 区块链 共识算法 分类
  7. OTDR系统的分类的特点
  8. 搭建 Spring Cloud Alibaba 微服务框架
  9. 【枚举的定义;枚举变量的定义、初始化和赋值】(学习笔记16--枚举)
  10. C语言共用体中,共用体变量的规律
  11. Python爬虫的起点,一文轻松入门
  12. c语言变量名用一个字母,C语言变量命名规则
  13. 2019年1月1日起,国家推出新的个人所得税政策,起征点上调值5000元。也就是说税前工资扣除五险一金(五险一金数额假设是税前工资的10%) * 后如果不足5000元,则不交税。
  14. python守护进程去中断子进程_04 Python并发编程(守护进程,进程锁,进程队列)
  15. 【Java高级程序设计学习笔记】深入理解jdk动态代理
  16. win10神州网信+UOS双系统安装步骤
  17. LM393比较器仿真
  18. IDEA使用Git远程推送出现push to origin/master was rejected错误解决方案
  19. echarts双y轴,自定义y轴显示字段
  20. word 2007 中的 aurora 插件配置

热门文章

  1. EXCEL实用技巧-多条件求和、多条件计数、多条件查找
  2. EasyDSS点播视频添加水印的位置与定义的位置不匹配怎么办?
  3. KOBAS数据库使用指南
  4. 管理Discuz!代码分析的收集整理
  5. 京东数据分析软件 | 如何获取京东平台的“增长榜单”
  6. 计算机组成原理三种译码方式,计算机组成原理第三章存储系统
  7. vus3+Ts Apache ECharts 的使用(可视化图表库)
  8. Java Cache 缓存方案详解及代码-Ehcache
  9. IntelliJ IDEA设置自动导入包
  10. 关于在win8下面安装虚拟机出现的一些问题