定義:(Bridge Pattern)
將抽象和實現(xiàn)解耦够坐,使得兩者可以獨(dú)立地變化托嚣。
類圖:
啟示:
一個產(chǎn)品的研發(fā)损趋,流程主要包括需求分析患久、產(chǎn)品設(shè)計、制定計劃浑槽、任務(wù)安排蒋失、進(jìn)度把控、產(chǎn)品發(fā)布桐玻、后期運(yùn)維篙挽。
按照我們一般的設(shè)計思路,我們可能會如下設(shè)計:
定義一個抽象的ProjectManager類镊靴,用來定義項目的開發(fā)流程铣卡,不同的項目通過繼承來實現(xiàn)具體的流程链韭。每增加新的項目,就只需要繼承該類重新實現(xiàn)即可煮落。但這僅適用于某個單一角色對產(chǎn)品的管理敞峭。
我們知道一個IT公司的組織架構(gòu)一般由CEO、產(chǎn)品經(jīng)理蝉仇、項目經(jīng)理和員工組成旋讹。CEO負(fù)責(zé)整個公司運(yùn)行項目的整體把控,產(chǎn)品經(jīng)理負(fù)責(zé)公司的某一條產(chǎn)品線轿衔,項目經(jīng)理則負(fù)責(zé)產(chǎn)品線中的某個項目的開發(fā)管理骗村,而員工就是負(fù)責(zé)項目的開發(fā)工作。
作為一名項目經(jīng)理呀枢,職責(zé)可能主要是制定開發(fā)計劃和任務(wù)分配胚股,并把控進(jìn)度。但若作為一名產(chǎn)品經(jīng)理裙秋,職責(zé)可能就需要額外負(fù)責(zé)需求分析琅拌、產(chǎn)品設(shè)計的工作,職位越高摘刑,責(zé)任越大嘛进宝。
按照之前的設(shè)計,我們就需要針對同一個項目不同的角色分別提供不同的實現(xiàn)枷恕,這顯然是不合理的党晋。且每個角色都被賦予了同樣的流程管理功能,這也是不符合現(xiàn)實場景的徐块。那如何做到項目管理根據(jù)不同角色和不同項目靈活變化呢未玻?要想做到這一點,我們就必須將之前項目管理和項目的緊耦合關(guān)系松松綁胡控。而如何松綁呢扳剿,咱們借助『橋接模式』。
Talk is cheap, show you the code!
代碼:
從面向?qū)ο蟮慕嵌戎缂ぃ覀兛梢猿橄蟪鼋?jīng)理和項目兩個對象庇绽,將這些工作流程抽象為具體的行為方法。
那這些行為方法的附屬該如何設(shè)置呢橙困?經(jīng)理作為項目的主要把控者瞧掺,以上的工作是經(jīng)理的職責(zé)所在。但是凡傅,這些工作又都是基于項目的辟狈,也就是說我們也可以將這些工作看成是項目本身的行為。你可能會按以人為本的思想像捶,將這些行為方法定義到經(jīng)理的角色里上陕。但這樣就會有一個問題,假設(shè)項目經(jīng)理在項目尚未結(jié)束的時候因為某些因素辭職了或人事變動調(diào)離了拓春,那之前的項目的工作安排就不可控了释簿,這是不允許的。所以最好還是把這些行為方法定義到具體的項目中去硼莽。
public abstract class Project
{
public string ProjectName { get; set; }
protected Project(string projectName)
{
ProjectName = projectName;
}
/// <summary>
/// 需求分析
/// </summary>
public abstract void AnalyzeRequirement();
/// <summary>
/// 產(chǎn)品設(shè)計
/// </summary>
public abstract void DesignProduct();
/// <summary>
/// 制定計劃
/// </summary>
public abstract void MakePlan();
/// <summary>
/// 任務(wù)分解
/// </summary>
public abstract void ScheduleTask();
/// <summary>
/// 進(jìn)度把控
/// </summary>
public abstract void ControlProcess();
/// <summary>
/// 產(chǎn)品發(fā)布
/// </summary>
public abstract void ReleaseProduct();
/// <summary>
/// 后期運(yùn)維
/// </summary>
public abstract void MaintainProduct();
}
那如何做到不同的角色賦予不同的項目管理職責(zé)呢庶溶?我們可以將職責(zé)最少的角色抽象出來。比如我們可以將項目經(jīng)理制定產(chǎn)品計劃懂鸵、任務(wù)分配和進(jìn)度把控抽離出來偏螺。
public abstract class Manager
{
protected Project CurrentProject { get; }
protected Manager(Project currentProject)
{
CurrentProject = currentProject;
}
/// <summary>
/// 制定計劃
/// </summary>
public abstract void SchedulePlan();
/// <summary>
/// 任務(wù)分配
/// </summary>
public abstract void AssignTasks();
/// <summary>
/// 進(jìn)度把控
/// </summary>
public abstract void ControlProcess();
/// <summary>
/// 項目管理
/// </summary>
public virtual void ManageProject()
{
SchedulePlan();
AssignTasks();
ControlProcess();
}
}
然后項目經(jīng)理和產(chǎn)品經(jīng)理繼承實現(xiàn)基本職責(zé),根據(jù)需要動態(tài)添加額外的職責(zé)匆光。
我們看看項目經(jīng)理的具體實現(xiàn):
/// <summary>
/// 項目經(jīng)理
/// </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($"項目經(jīng)理負(fù)責(zé)【{base.CurrentProject.ProjectName}】:");
base.ManageProject();
}
}
再看看產(chǎn)品經(jīng)理的實現(xiàn):
/// <summary>
/// 產(chǎn)品經(jīng)理
/// </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($"產(chǎn)品經(jīng)理負(fù)責(zé)【{base.CurrentProject.ProjectName}】:");
AnalyseRequirement();
DesignProduct();
base.ManageProject();
}
}
可以看到我們?yōu)楫a(chǎn)品經(jīng)理額外添加了需求分析和產(chǎn)品設(shè)計的職責(zé)套像。
下面我們看看最終的場景類:
Project webProject = new WebProject("Web項目");
Manager projectManager = new ProjectManager(webProject);
Manager productManager = new ProductManger(webProject);
projectManager.ManageProject();
productManager.ManageProject();
Console.ReadLine();
總結(jié):
通過上面的demo,我們解決了之前通過繼承設(shè)計的弊端终息,即項目管理和項目不能靈活適應(yīng)變化夺巩。通過引入橋接模式,將項目管理和項目解耦周崭,我們實現(xiàn)了項目管理(抽象)和項目(實現(xiàn))的分離柳譬。橋接模式的意圖還是對變化的封裝,盡量把可能變化的因素封裝到最細(xì)续镇、最小的邏輯單元中美澳,避免風(fēng)險擴(kuò)散。而這也正是橋接模式的精髓所在摸航。
優(yōu)缺點:
橋接模式將抽象和實現(xiàn)分離制跟,實現(xiàn)可以不受抽象的約束,不用再綁定在一個固定的抽象層次上酱虎;抽象和實現(xiàn)均可自由擴(kuò)展凫岖。
應(yīng)用場景:
- 不希望或不適用使用繼承的場景
- 接口或抽象類不穩(wěn)定的場景
- 重用性要求較高的場景
- 解決多層繼承
實際案例:
數(shù)據(jù)庫:Orace、SQL Server
數(shù)據(jù)庫訪問技術(shù):NHibernate逢净、EntityFramework
每種數(shù)據(jù)庫都可以用不同的數(shù)據(jù)庫訪問技術(shù)汪拥。