桥梁模式和战略模式之间有什么区别?

时间:2009-01-21 09:09:14

标签: design-patterns strategy-pattern bridge

我试图在dofactory,维基百科和许多网站上阅读很多文章。 我不知道桥梁模式和战略模式之间的差异。

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

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

14 个答案:

答案 0 :(得分:62)

语义。来自wikipedia

  

策略的UML类图   pattern与图表相同   桥模式。但是,这两个   设计模式不一样   他们的意图。而战略   模式是为了行为,   桥梁图案用于结构。

     

上下文与之间的耦合   战略比战略更紧密   抽象与抽象之间的耦合   桥中的实施   图案。

据我所知,当你抽象出可以从外部源提供的行为时(例如,config可以指定加载一些插件程序集),你正在使用策略模式,并且你正在使用桥接模式当你使用相同的结构使你的代码更整洁。实际代码看起来非常相似 - 您只是将模式应用于略有不同的原因

答案 1 :(得分:53)

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

语法类似,但目标不同:

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

答案 2 :(得分:10)

策略:

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

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

答案 3 :(得分:7)

Bridge (结构模式)

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

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

  1. 在编译时尚未确定抽象和实现
  2. 抽象和实施应该独立更改
  3. 抽象实现的变化不应影响调用者应用程序
  4. 客户应与实施细节隔离。
  5. 策略: (行为模式)

    策略模式使您可以在运行时从一系列算法中切换多个算法。

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

    1. 需要多个版本的算法
    2. 必须在运行时动态更改类的行为
    3. 避免条件陈述
    4. 相关帖子:

      When do you use the Bridge Pattern? How is it different from Adapter pattern?

      Real World Example of the Strategy Pattern

答案 4 :(得分:5)

我的想法是一样的,但最近我不得不使用网桥并意识到网桥正在使用策略并在上下文中添加抽象,以便您以后可以在不更改客户端的情况下进行更多更改。在没有抽象的情况下使用策略时,设计不够灵活,可能需要稍后更改客户端。但是当使用整个桥时,设计变得更加灵活。在这里,您可以了解从策略到桥梁的更多灵活性。我们也假设现在" visa"和#34;主人"不仅可以在卡上使用,也可以在手机和芯片上使用;如果我们使用bridge,则添加该支持要容易得多。

Strategy VS Bridge

答案 5 :(得分:2)

添加到willcodejavaforfood的答案,它们可以在实现中相同。但是,您使用策略来交换策略(例如排序策略),而您使用桥接来桥接两个对象的实现,例如数据库包装器和网络适配器,因此客户端代码可以使用针对相同API的工作。所以这个命名实际上都说明了一切

答案 6 :(得分:2)

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

  2. Brigde 模式将抽象元素与实现细节分开,而策略模式则涉及使算法更具可互换性。

  3. Strategy Pattern in UML

    Brigde Pattern in UML

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

答案 7 :(得分:1)

来自Strategy模式的wiki

  

策略的UML类图   pattern与图表相同   桥模式。但是,这两个   设计模式不一样   他们的意图。而战略   模式是为了行为,   桥梁图案用于结构。

     

上下文与之间的耦合   战略比战略更紧密   抽象与抽象之间的耦合   桥中的实施   图案。

答案 8 :(得分:1)

只是添加已经说过的关于模式比较(意图的差异,......):桥模式也是有意构造的,以允许抽象层次方改变。在像C#这样的语言中,这可能意味着您有一个包含虚拟方法的抽象基础,作为允许不会给现有消费者带来问题的预期变体的一种方式。除此之外,这两种模式在大多数情况下可能看起来相同。

答案 9 :(得分:1)

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

答案 10 :(得分:1)

设计模式类型

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

Bridge(结构性)

  

将抽象与其实现分离,以便每个抽象都可以变化。   独立。   enter image description here

拿一个遥控器。遥控器有按钮1-6。这是上图中的具体类。每个按钮的工作方式都不同,具体取决于遥控器是用于电视还是DVD。实现者界面从实现中抽象出每个按钮的功能。

这允许我们更改遥控器对每个设备的工作方式。

Strategy(行为)

  

定义一系列算法,封装每个算法并使它们可互换。   enter image description here

在策略中,如果我们正在查看远程场景。 “state”是我们通过更改上下文的状态引用而换出的整个远程。 “concreteStateA”(电视遥控器)“concreteStateB”(DVD遥控器)。

补充阅读:

答案 11 :(得分:0)

对于战略模式,只有实施方式不同。

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

现在,如果A本身是抽象的。 A和B都可能有所不同。你会使用Bridge模式。

答案 12 :(得分:0)

我认为他们在使用环境中存在细微差别。

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

IMO,战略模式更简单或更平坦。它确实适用于OCP,但不一定是另一个更大的概念,如Bridge模式。

答案 13 :(得分:0)

在策略模式中,特定操作的“父级”活动是恒定的,而“子级”的活动可以变化。但是,在“桥接模式”中,父级和子级的活动可能会有所不同。

例如,

free(array_of_struct[i].arr);

在上面,变化取决于父级(距离)以及子级(车辆和座位)。因此,这里的Vehicle和Seat都像Bridge一样。

现在,在这里

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

    }
    
}

在这里,父母的角色是不变的,即什么也没有!因此,这是一种策略模式。