目录
3.3 修正抽象化角色(RefinedAbstraction)
3.4 具体实现化角色(ConcreteImplementor)
一、设计模式入门指南:桥接模式登场
在软件开发的广袤世界里,设计模式宛如熠熠生辉的灯塔,为开发者照亮前行的道路,指引着他们解决一个又一个复杂的问题。设计模式是前辈们智慧的结晶,是经过无数次实践验证的、可复用的解决方案。它就像是一套精心打磨的工具套装,当我们面对各种编程难题时,总能从中找到合适的 “工具”,让代码更加优雅、高效、易于维护。
想象一下,你正在建造一座宏伟的大厦,如果没有合理的设计蓝图和施工方法,只是盲目地堆砌砖块,最终的结果可能是大厦摇摇欲坠,甚至无法建成。同样,在软件开发中,如果没有设计模式的指导,代码可能会变得混乱不堪,难以扩展和维护。设计模式帮助我们将复杂的系统拆解为一个个清晰、独立的模块,让各个模块之间的协作更加顺畅,就像大厦的各个部分紧密配合,共同支撑起整个建筑的稳定。
今天,我们要一同探索设计模式家族中的一位重要成员 —— 桥接模式。桥接模式,光听名字,是不是就感觉它像一座桥梁,连接着不同的部分?没错,它的作用正如其名,能够巧妙地将抽象部分与实现部分分离,使它们可以独立地变化。这一特性在应对复杂系统中多个维度变化的问题时,展现出了巨大的优势,让我们能够轻松地拓展系统的功能,而不必担心牵一发而动全身。接下来,就让我们深入桥接模式的奇妙世界,揭开它神秘的面纱吧!
二、什么是桥接模式
2.1 定义与概念
桥接模式(Bridge Pattern)是一种结构型设计模式,它的核心定义正如前文所说,是将抽象部分与实现部分分离,使它们可以独立地变化 。简单来说,就是把原本紧密耦合在一起的抽象概念和具体实现分离开来,让它们能够各自沿着自己的方向发展,互不干扰。
为了更好地理解,我们来打个比方。假如你正在开发一款游戏,游戏中有不同类型的角色,比如战士、法师、刺客,同时这些角色又可以装备不同属性的武器,像攻击力加成的剑、魔法伤害提升的法杖、暴击率增加的匕首。如果不使用桥接模式,我们可能会为每个角色与武器的组合创建一个新的类,比如战士持剑类、战士持法杖类、法师持剑类等等,这样一来,类的数量会随着角色和武器种类的增加而急剧膨胀,代码的维护和扩展将变得异常艰难。
而使用桥接模式,我们可以将角色和武器分别抽象成两个独立的维度。角色维度有战士、法师、刺客等抽象类,武器维度有剑、法杖、匕首等抽象类,然后通过桥接的方式,让角色类持有武器类的引用,这样就可以灵活地组合不同角色和武器,而不需要创建大量冗余的类。例如,战士类可以持有剑类的引用,实现战士持剑的功能;法师类可以持有法杖类的引用,实现法师持法杖的功能。当我们需要新增一种角色或者武器时,只需要在各自的维度中添加新的类,而不会影响到另一个维度的代码。
2.2 核心原理剖析
桥接模式的核心原理是通过组合(Composition)而非继承(Inheritance)来建立抽象部分和实现部分之间的联系。这种方式打破了传统的继承关系所带来的强耦合,使得系统更加灵活和可扩展。
从实现层面来看,桥接模式主要包含以下几个关键角色,我们结合 UML 图(此处假设你能在脑海中构建一个简单的桥接模式 UML 图框架,抽象类 Abstraction 与实现接口 Implementor 通过聚合关系相连,RefinedAbstraction 继承自 Abstraction,ConcreteImplementorA 和 ConcreteImplementorB 实现 Implementor 接口)来深入理解:
-
抽象类(Abstraction):它定义了抽象的接口,这个接口通常包含一些抽象方法,用于描述系统的抽象行为。同时,它持有一个实现部分的引用,通过这个引用,抽象类可以调用实现部分的具体方法,从而实现抽象与实现的关联。例如,在刚才的游戏例子中,角色抽象类就定义了角色的基本行为,如攻击、防御等抽象方法,并且持有武器抽象类的引用。
-
扩展抽象类(RefinedAbstraction):是抽象类的具体实现子类,它在继承抽象类的基础上,可能会增加一些新的方法或者重写抽象类中的方法,以满足更具体的业务需求。比如游戏中的战士类,它继承自角色抽象类,并且可能会增加一些战士特有的技能,如冲锋、斩杀等。
-
实现接口(Implementor):定义了实现部分的接口,这个接口中声明的方法是实现抽象类中抽象方法的具体操作。它不一定与抽象类的接口完全一致,但抽象类会通过调用实现接口中的方法来完成具体的功能。在游戏中,武器抽象类就定义了武器的基本操作,如攻击方式、伤害计算等接口方法。
-
具体实现类(ConcreteImplementor):是实现接口的具体实现类,它实现了实现接口中定义的所有方法,提供了具体的实现逻辑。例如游戏中的剑类、法杖类、匕首类,它们分别实现了武器抽象类的接口方法,具体定义了剑的攻击方式是近战物理攻击、法杖的攻击方式是远程魔法攻击、匕首的攻击方式是近战暴击攻击等。
通过这样的结构,当我们需要扩展抽象部分时,只需要创建新的扩展抽象类;当需要扩展实现部分时,只需要创建新的具体实现类。两者之间通过桥接(即抽象类持有实现接口的引用)相互协作,却又互不干扰,实现了高度的解耦。
三、桥接模式的组成角色
3.1 抽象化角色(Abstraction)
抽象化角色处于桥接模式结构的高层,它就像是一个总指挥,定义了系统的抽象行为和架构。在代码中,抽象化角色通常以抽象类的形式出现,它声明了一系列抽象方法,这些方法描述了系统需要完成的核心功能。同时,它持有一个对实现化角色的引用,就像指挥官需要有具体的执行者来完成任务一样。通过这个引用,抽象化角色可以调用实现化角色的具体实现方法,从而将抽象的行为与具体的实现联系起来 。
例如,在一个图形绘制系统中,抽象化角色可以是 “Shape” 抽象类,它定义了 “draw” 抽象方法,用于绘制图形。同时,它持有一个对 “Color” 实现化角色的引用,因为绘制图形时需要指定颜色。这样,“Shape” 抽象类就可以通过调用 “Color” 实现化角色的方法来完成图形的绘制,将图形绘制的抽象行为与颜色实现分离开来,使得图形和颜色可以独立变化。
3.2 实现化角色(Implementor)
实现化角色是桥接模式中负责提供具体实现的部分,它通常是一个接口或者抽象类。实现化角色定义了一系列方法和属性,这些方法和属性是实现抽象化角色中抽象方法所必需的。它并不直接与客户端交互,而是为抽象化角色提供底层的实现支持 。
继续以上述图形绘制系统为例,“Color” 接口就是实现化角色,它定义了 “paint” 方法,用于绘制颜色。不同的颜色实现类,如 “RedColor”、“BlueColor” 等,会实现 “Color” 接口的 “paint” 方法,提供具体的颜色绘制逻辑。而 “Shape” 抽象类在实现 “draw” 方法时,会调用 “Color” 接口的 “paint” 方法,从而实现图形的绘制,并应用指定的颜色。
3.3 修正抽象化角色(RefinedAbstraction)
修正抽象化角色是抽象化角色的具体实现子类,它在继承抽象化角色的基础上,进一步细化和扩展了抽象化角色的功能。修正抽象化角色通过调用实现化角色的方法,来完成具体的业务逻辑。它不仅实现了抽象化角色中定义的抽象方法,还可能会增加一些新的方法或者重写抽象化角色中的方法,以满足特定的业务需求 。
在图形绘制系统中,“Circle” 类和 “Rectangle” 类可以作为修正抽象化角色,它们继承自 “Shape” 抽象类。“Circl