桥接模式和策略模式有什么区别?


114

我试图阅读有关工厂,维基百科和许多站点的许多文章。我对桥接模式和策略模式之间的差异一无所知。

我知道它们都将抽象与实现分离开来,并且可以在运行时更改实现。

但是我仍然不知道在哪种情况下应该使用策略或在哪种情况下应该使用桥接。

Answers:


66

语义学。来自维基百科

Strategy模式的UML类图与Bridge模式的图相同。但是,这两种设计模式的意图并不相同。策略模式用于行为,而桥接模式用于结构。

上下文和策略之间的耦合比桥接模式中抽象和实现之间的耦合更紧密。

据我了解,当您抽象可能由外部来源提供的行为时,您正在使用策略模式(例如config可以指定加载某些插件程序集),而当您使用相同的构造使您的代码更加整洁。实际的代码看起来非常相似-您只是出于稍微不同的原因应用模式。


3
所以我可以说我正在使用策略模式来抽象行为,同时也使代码看起来像在桥接模式中一样整齐。像策略模式一样抽象行为?我说的对吗?
user20358'2

1
两者之间的区别仅在于目的。因此,我猜我们可以放心地说,因为它们都使用相同的想法并提供相同的灵活性,所以这两种模式在功能上是相同的。
Elz 2015年

3
在我的GoF书中,Bridge的UML完全不同该工具能够区分Bridge和Strategy。
Fuhrmanator

1
维基百科通常是一个可怕的参考。正确的是,该错误信息已从页面中删除。en.wikipedia.org/w/…–
Fuhrmanator

2
我得到的方式是使用相同的技术来抽象实现(策略)或抽象接口(桥)。策略交换行为,桥接交换接口(这最终允许交换具有此类接口的实现)。换句话说,Bridge在一侧创建标准化接口,而在另一侧插入具有不同接口的实现。
Nikaas

55

桥接模式是一种结构模式(您如何构建软件组件?)。策略模式是动态模式(您如何在软件中运行行为?)。

语法相似,但目标不同:

  • 策略:您有更多的操作方法;使用策略时,您可以在运行时选择算法,并且可以在编译时修改单个策略而不会产生很多副作用。
  • :您可以拆分接口和类的层次结构,并将其与抽象引用结合在一起(请参阅extraction

3
因此,如果语法相似,那么我是否会正确地说我正在使用这两种模式中的任何一种以特定方式运行软件行为,还因为我想以这种方式构建组件,因此看起来也很整洁?
user20358'2

11

战略:

  • 与策略相关联的上下文:上下文类(可能是抽象类,但不是真正的接口!因为您希望封装特定行为,而不是整个实现),所以它将知道/包含策略接口引用和实现,以在其上调用策略行为它。
  • 目的是在运行时交换行为的能力

    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();
    
          }
    
          .............
    
    }
    

10

我当时的想法是一样的,但是最近我不得不使用网桥,并意识到网桥正在使用策略并向上下文中添加抽象,以便您以后可以进行更多更改而无需更改客户端。当使用不带抽象的策略时,设计不那么灵活,以后可能需要更改客户端。但是,当使用整个桥时,设计将变得更加灵活。在这里,您可以了解如何从“战略”过渡到“桥梁”如何提供更大的灵活性。我们还假设现在“ visa”和“ master”不仅可以在卡上使用,而且还可以在手机和芯片上使用;如果我们使用网桥,则添加该支持要容易得多。

策略VS桥


9

:(一种结构模式)

桥接模式将抽象和实现解耦,并允许两者独立变化。

在以下情况下使用此模式:

  1. 尚未在编译时确定抽象和实现
  2. 抽象和实现应独立更改
  3. 抽象实现的更改不应影响调用者的应用程序
  4. 客户应与实施细节隔离。

策略:(行为模式)

策略模式使您可以在运行时在一系列算法中的多种算法之间进行切换。

在以下情况下使用策略模式:

  1. 需要多种版本的算法
  2. 必须在运行时动态更改类的行为
  3. 避免条件语句

相关文章:

什么时候使用桥接模式?与适配器模式有何不同?

战略模式的真实例子


4

设计模式类型

  • 行为:模式描述了类或对象交互和分配责任的方式
  • 结构:模式处理类或对象的组成。
  • Creational: 模式关注对象创建的过程。

桥梁(结构)

将抽象与其实现分离开来,以便每个抽象都可以变化。独立地。 在此处输入图片说明

拿一个遥控器。遥控器具有按钮1-6。这是上图中的具体类。每个按钮的作用会有所不同,具体取决于遥控器是用于电视还是DVD。每个按钮的功能都是通过实现者接口从实现中抽象出来的。

这使我们可以更改遥控器在每种设备上的工作方式。

策略(行为)

定义一系列算法,封装每个算法并使它们可互换。 在此处输入图片说明

在策略上,如果我们正在研究远程方案。“状态”是我们通过更改上下文的状态引用交换出来的整个远程对象。“ concreteStateA”(电视遥控器)“ concreteStateB”(DVD遥控器)。

补充阅读:


3
  1. 策略模式用于行为决策,而桥接模式用于结构决策。

  2. Brigde Pattern从实现细节中分离出抽象元素,而Strategy Pattern则关注使算法更具互换性。

UML中的策略模式

UML中的Brigde模式

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中的Brigde模式:

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()

为什么只有战略模式才能更“互换”。正如我们在代码示例中所演示的那样,由于我们编写的是接口而不是实现的代码,因此可以在策略中交换实现或桥接,如您在代码示例中所演示的那样,Stereo与进行交换即可TV使代码正常工作。
denis631

2

除了willcodejavaforfood的答案外,它们在实现上可以相同。但是,您使用策略来交换诸如排序策略之类的策略,同时使用Bridge来桥接两个对象(例如数据库包装程序)和网络适配器的实现,因此客户端代码可以使用针对相同API的任何一种。所以命名实际上说明了一切


1

来自策略模式的维基

Strategy模式的UML类图与Bridge模式的图相同。但是,这两种设计模式的意图并不相同。策略模式用于行为,而桥接模式用于结构。

上下文和策略之间的耦合比桥接模式中抽象和实现之间的耦合更紧密。


您能详细说明一下吗?
gstackoverflow

1

只是为了补充关于模式比较(意图的差异,...)的内容:Bridge模式也是有意构造的,以允许抽象层次结构方面有所不同。在像C#这样的语言中,这可能意味着您拥有一个包含虚拟方法的抽象库,以此作为允许有意进行的变化而不会对现有使用者造成问题的方式。除此之外,这两种模式在大多数情况下可能看起来相同。


1

当您希望在运行时插入算法或策略时,将使用策略模式。作为模式类别还意味着它处理对象的行为。另一方面,桥梁是结构模式,处理对象的结构层次。通过在它们之间引入改进的抽象,它将抽象与实现分离。精致的抽象可能与插入的运行时策略(在策略模式中)混淆。桥接模式通过提供避免创建n个类的机制来处理结构方面。


1

对于策略模式,仅实现方式有所不同。

假设类A使用的类B具有多种可用实现。因此,在那种情况下,B将是抽象的,并在运行时提供了实际的实现。这是策略模式

现在,如果A本身是抽象的。A和B可能都不同。您将使用桥接模式。


0

我认为在使用它们的上下文中它们之间有细微的差别。

我使用Bridge模式来分离它们都属于一个较大的正交概念-让它们独立地变化。它通常涉及多个抽象。

IMO,战略模式更简单或更平坦。它肯定对OCP有用,但不一定要成为另一个更大概念(如Bridge模式)的一部分。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.