我知道它们都将抽象与其实现分离,并可以在运行时更改实现。但是我仍然不知道在哪种情况下应该使用策略模式,在哪种情况下应该使用桥接模式。
据我所知,当您需要抽象可能来自外部来源的行为时(例如,配置可以指定加载某个插件程序集),您使用策略模式;而当您使用相同的结构使您的代码更整洁时,则使用桥接模式。 实际代码看起来非常相似-您只是出于略有不同的原因应用这些模式。策略模式的 UML 类图与桥接模式相同。但是,这两种设计模式在意图上不同。虽然策略模式用于行为,但桥接模式用于结构。
上下文和策略之间的耦合比桥接模式中抽象和实现之间的耦合要紧密。
桥接模式是一种结构性模式(如何构建软件组件?)。策略模式是一种动态模式(如何在软件中运行行为?)。
语法相似但目标不同:
策略:
意图是在运行时交换行为能力。
class Context {
IStrategy strategyReference;
void strategicBehaviour() {
strategyReference.behave();
}
}
桥接模式
目的是完全将抽象化与实现解耦。
interface IAbstraction {
void behaviour1();
.....
}
interface IImplementation {
void behave1();
void behave2();
.....
}
class ConcreteAbstraction1 implements IAbstraction {
IImplementation implmentReference;
ConcreteAbstraction1() {
implmentReference = new ImplementationA() // Some implementation
}
void behaviour1() {
implmentReference.behave1();
}
.............
}
class ConcreteAbstraction2 implements IAbstraction {
IImplementation implmentReference;
ConcreteAbstraction1() {
implmentReference = new ImplementationB() // Some Other implementation
}
void behaviour1() {
implmentReference.behave2();
}
.............
}
桥接模式: (一种结构型模式)
桥接模式将抽象和实现分离,使得两者可以独立变化。
使用此模式的情况包括:
策略模式: (一种行为型模式)
策略模式允许您在运行时从算法族中切换多个算法。
使用策略模式的情况包括:
相关帖子:
策略模式 用于行为决策,而 桥接模式 用于结构决策。
桥接模式 将抽象元素与实现细节分离,而策略模式 则关注使算法更具可互换性。
Swift 中的策略模式:
protocol PrintStrategy {
func print(_ string: String) -> String
}
class Printer {
let strategy: PrintStrategy
init(strategy: PrintStrategy) {
self.strategy = strategy
}
func print(_ string: String) -> String {
return self.strategy.print(string)
}
}
class UpperCaseStrategy: PrintStrategy {
internal func print(_ string: String) -> String {
return string.uppercased()
}
}
class LowerCaseStrategy: PrintStrategy {
internal func print(_ string: String) -> String {
return string.lowercased()
}
}
var lower = Printer(strategy: LowerCaseStrategy())
lower.print("I love Software Patterns")
var upper = Printer(strategy: UpperCaseStrategy())
upper.print("I love Software Patterns")
Swift中的桥接模式:
protocol Appliance {
func run()
}
protocol Switch {
let appliance: Appliance {get set}
func turnOn()
}
class RemoteControl: Switch {
var appliance: Appliance
init(appliance: Appliance) {
self.appliance = appliance
}
internal func turnOn() {
appliance.run()
}
}
class TV: Appliance {
internal func run() {
print("TV is ON")
}
}
class Stereo: Appliance {
internal func run() {
print("Stereo is ON")
}
}
var tvRemote = RemoteControl.init(appliance: TV())
tvRemote.turnOn()
var stereoRemote = RemoteControl.init(appliance: Stereo())
stereoRemote.turnOn()
补充willcodejavaforfood的回答,它们在实现上可以相同。然而,你使用策略模式来交换策略,例如排序策略,而你使用桥接模式来桥接两个对象的实现,比如数据库包装器和网络适配器,这样客户端代码就可以使用任何一个针对相同API的工作。因此,命名实际上已经说明了一切。