我尝试阅读有关dofactory、维基百科和许多网站的许多文章。我不知道桥接模式和策略模式之间的区别。
我知道它们都将抽象与其实现分离,并且可以在运行时更改实现。
但是我还是不知道在什么情况下应该使用策略,或者在什么情况下应该使用桥牌。
我尝试阅读有关dofactory、维基百科和许多网站的许多文章。我不知道桥接模式和策略模式之间的区别。
我知道它们都将抽象与其实现分离,并且可以在运行时更改实现。
但是我还是不知道在什么情况下应该使用策略,或者在什么情况下应该使用桥牌。
语义。来自维基百科:
策略模式的 UML 类图与桥模式的图相同。但是,这两种设计模式的意图并不相同。策略模式适用于行为,而桥接模式适用于结构。
上下文和策略之间的耦合比桥接模式中抽象和实现之间的耦合更紧密。
据我了解,当您抽象可以从外部源提供的行为(例如,配置可以指定加载某些插件程序集)时,您正在使用策略模式,并且您在使用时使用桥接模式相同的结构使您的代码更整洁。实际代码看起来非常相似 - 您只是出于稍微不同的原因应用这些模式。
The Bridge pattern is a structural pattern (HOW DO YOU BUILD A SOFTWARE COMPONENT?). The Strategy pattern is a dynamic pattern (HOW DO YOU WANT TO RUN A BEHAVIOUR IN SOFTWARE?).
The syntax is similar but the goals are different:
I was thinking the same, but recently I had to use bridge and realized that bridge is using strategy and adding abstraction to the context so that you later can make more changes without changing the client. When using Strategy without the abstraction the design is not as flexible and may require changes to the client later. But when using the whole bridge the design becomes even more flexible. Here you can se how going from Strategy to Bridge gives more flexibility. Also we assume that now "visa" and "master" are not only available on cards but on phones and chips also; and if we use bridge it is much easier to add that support.
Strategy:
Intent is ability to swap behavior at runtime
class Context {
IStrategy strategyReference;
void strategicBehaviour() {
strategyReference.behave();
}
}
Bridge
Intent is to completely decouple the Abstraction from the Implementation
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();
}
.............
}
Bridge: ( A structural pattern)
Bridge pattern decouples abstraction and implementation and allows both to vary independently.
Use this pattern when :
Strategy: ( Behavioural pattern)
Strategy patterns enable you to switch between multiple algorithms from a family of algorithms at run time.
Use Strategy pattern when :
Related posts:
When do you use the Bridge Pattern? How is it different from Adapter pattern?
Design pattern types
Bridge (Structural)
Decouple an abstraction from its implementation so that each may vary. independently.
Take a remote. The remote has buttons 1-6. This is the concrete class in the diagram above. Each button will work different depending on if the remote is used for a TV or DVD. The functionality for each button is abstracted from the implementation by the implementer interface.
This allows us to change how the remote will work for each device.
Strategy (Behavioural)
Define a family of algorithms , encapsulate each one and make them interchangeable.
In strategy, if we were looking at the remote scenario. The "state" is the entire remote which we swap out by changing the context's state reference. The "concreteStateA" (TV remote) "concreteStateB" (DVD Remote).
Additional reading:
Strategy Pattern is used for Behavioural decisions, while Bridge Pattern is used for Structural decisions.
Brigde Pattern separats the abstract elements from the implementation details, while Strategy Pattern is concerned making algorithms more interchangeable.
Strategy Pattern in 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")
Brigde Pattern in 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。所以命名实际上说明了一切
来自关于策略模式的 wiki
策略模式的 UML 类图与桥模式的图相同。但是,这两种设计模式的意图并不相同。策略模式适用于行为,而桥接模式适用于结构。
上下文和策略之间的耦合比桥接模式中抽象和实现之间的耦合更紧密。
Just to add to what has already been said about the pattern comparison (difference of intent, ...): the Bridge pattern is also intentionally structured to allow the abstraction hierarchy side to vary. In languages like C# this could imply you have an abstraction base that contains virtual methods as a way to allow intended variations that don't cause problems for existing consumers. Other than that the two patterns might appear identical for the most part.
Strategy pattern is used when you wish to plug algorithm or strategy at run time. As category of pattern also implies that it deals with behaviour of the objects. On the other hand bridge is structural pattern and deals with structural hierarchy of the objects. It decouples the abstraction from implementation by introducing a refined abstraction between them. Refined abstraction can be confused with the run time strategy plugged (In Strategy pattern). Bridge pattern deals with the structural aspects by providing a mechanism to avoid creating n number of classes.
For strategy pattern only the implementation varies.
Suppose, class A is using class B which has multiple implementations available. So in that case B would be abstract with actual implementation provided at runtime. This is strategy pattern
Now if A itself is abstract. Both A and B may vary. You would use Bridge pattern.
I think there's a slight difference between them in the context they're being used.
I use the Bridge pattern to separate orthogonal concepts which they both belong to a bigger one - to let them vary independently. It usually involves multiple abstractions.
IMO, the Strategy pattern is simpler or more flat. It serves to OCP for sure but doesn't necessarily to be part of another and bigger concept like the Bridge pattern.
In the Strategy pattern, the activities of the "Parent" for a particular operation are constant whereas the activities of the "Child" can vary. However, in the Bridge Pattern, the activities of the Parent, as well as the Child, can vary.
So, for example,
public class Ticket {
Date dateOfTravel;
int distance;
Vehicle vehicle;
Seat seat;
public float getTotalFare(){
//depends on
//Distance
//Vehicle - whether Vehicle is AC or non-AC.
//Seat - based on the location of the Seat.
//Fare = vehicleBaseFare*seatMultiplier*distance
}
}
In the above, the variations depend on the Parent (distance) as well as the children (Vehicle and Seat). So, here Vehicle and Seat both acted like Bridge.
Now, here
public class Vehicle {
TrackingDevice device;
public Coordinates getCoordinates(){
return device.getCoordinates();
}
}
Here, the Parent's role was constant, i.e., nothing! So, this was a Strategy pattern.