- 本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
桥接模式(Bridge Pattern): 是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。也可以理解为将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
模式理解
桥接模式结构
- 抽象化(Abstraction):定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction):是抽象化角色的子类,提供控制逻辑的变体。 与其父类一样, 它们通过通用实现接口与不同的实现进行交互。。
- 实现化(Implementor):定义实现化的接口,供扩展抽象化角色调用。
- 具体实现(Concrete Implementor):给出接口的具体实现。
业务场景
假设现有Oppo手机,想要安装一款游戏软件我们代码应该如何实现
public interface GameSoftware //游戏软件接口
{
void PlayGame();//实现了打游戏方法
}
// Oppo手机类继承游戏软件,实现PlayGame方法
public class OppoGame : GameSoftware
{
public void PlayGame()
{
Console.WriteLine("使用Oppo手机安装游戏软件打游戏!");
}
}
思考:这样设计扩展性确实很强,我们设想一下,现在又出现一手机产品Vivo,也要实现下载游戏软件打游戏此时我们新增OppoGame实现GameSoftware实现方法,如果此时需要下载笔记本软件写笔记,这个时候会产生多少类?
实现桥接模式
针对上述问题,使用桥接模式可以非常好的解决,我们可以换一个角度想一下。如果我们将手机软件与手机解耦是不是可以很好的解决这个问题?我们将
手机与软件抽象出来,使他们的实现都彼此独立,可以看如下代码。
// 抽象软件接口,实现安装方法
public interface ISoftware
{
void Install();
}
// 继承软件接口,实现游戏安装
public class GameSoftware : ISoftware
{
public void Install()
{
Console.WriteLine("安装游戏软件");
}
}
// 继承软件接口,实现记事本安装
public class NotepadSoftware : ISoftware
{
public void Install()
{
Console.WriteLine("安装记事本软件");
}
}
- 抽象手机出来,然后通过实现接口与不同接口交互
//抽象手机接口,实现使用手机方法
public interface IPhone
{
void UsePhone();
}
//Oppo手机类继承手机接口,构造函数引入软件接口
public class OppoPhone: IPhone
{
private ISoftware software;
public OppoPhone(ISoftware _software)
{
software = _software;
}
public void UsePhone()
{
Console.WriteLine("使用Oppo手机");
software.Install();
}
}
//Vivo手机类继承手机接口,构造函数引入软件接口
public class VivoPhone: IPhone
{
private ISoftware software;
public VivoPhone(ISoftware _software)
{
software = _software;
}
public void UsePhone()
{
Console.WriteLine("使用Vivo手机");
software.Install();
}
}
- 调用实现
无论我们新增手机产品类,或者是新增软件类型,都无需修改现有类,直接扩展即可,新增类的个数也只是一个。
总结
由于实现方式的多样化,我们就需要把他们实现的独立起来,让他们各自变化,这样就不会影响其他实现,符合软件设计原则的开闭原则。从上面代码可以看出,使用桥接模式,能有效地减少非常多无效的类,减少维护成本。当然桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计。