【问题标题】:What is the difference between the bridge pattern and the strategy pattern?桥接模式和策略模式有什么区别?
【发布时间】:2010-10-02 15:31:20
【问题描述】:

我尝试阅读dofactory、维基百科和许多网站上的许多文章。 我不知道桥接模式和策略模式之间的区别。

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

但我还是不知道在什么情况下应该使用策略,在什么情况下应该使用桥接。

【问题讨论】:

    标签: design-patterns strategy-pattern bridge


    【解决方案1】:

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

    例如,

    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
    
        }
        
    }
    

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

    现在,这里

    public class Vehicle {
    
       TrackingDevice device;
    
       public Coordinates getCoordinates(){
           return device.getCoordinates();
       }
    }
    

    在这里,父母的角色是不变的,即什么都没有!所以,这是一个策略模式。

    【讨论】:

      【解决方案2】:

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

      语法相似但目标不同:

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

      【讨论】:

      • 所以如果语法相似,我是否正确地说我正在使用这些模式中的任何一个以特定方式运行软件行为,并且因为我想以这种方式构建组件所以它看起来也很整洁?
      【解决方案3】:

      语义。来自wikipedia

      策略的 UML 类图 模式与图相同 桥模式。然而,这两个 设计模式在 他们的意图。而战略 模式是为了行为, 桥接模式适用于结构。

      上下文和上下文之间的耦合 策略比 抽象和之间的耦合 在 Bridge 中的实施 模式。

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

      【讨论】:

      • 所以我可以说我正在使用策略模式来抽象行为,同时还使代码看起来像桥模式中一样整洁......或者,我正在使用桥模式来制作代码更整洁,还因为它允许我抽象策略模式中的行为?我是对的吗?
      • 两者的区别仅在于他们的意图。所以我想我们可以有把握地说,因为它们都使用相同的想法并提供相同的灵活性,所以这两种模式在功能上是相同的。
      • Bridge's UML 在我的 GoF 书籍副本中完全不同This tool 能够区分 Bridge 和 Strategy。
      • 维基百科通常是一个糟糕的参考。正确地,该错误信息已从页面中删除。 en.wikipedia.org/w/…
      • 我得到它的方式是使用相同的技术来抽象实现(策略)或抽象接口(桥)。策略交换行为,桥交换接口(这最终允许交换具有此类接口的实现)。换句话说,Bridge 一方面创建标准化接口,另一方面插入具有不同接口的实现。
      【解决方案4】:

      设计模式类型

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

      Bridge(结构)

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

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

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

      Strategy(行为)

      定义一系列算法,封装每个算法并使其可互换。

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

      补充阅读:

      【讨论】:

        【解决方案5】:

        :(一种结构模式)

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

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

        1. 在编译时还没有决定抽象和实现
        2. 应独立更改抽象和实现
        3. 抽象实现的更改不应影响调用方应用程序
        4. 客户端应与实现细节隔离。

        策略:(行为模式)

        策略模式使您能够在运行时在一系列算法中的多个算法之间切换。

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

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

        相关帖子:

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

        Real World Example of the Strategy Pattern

        【讨论】:

          【解决方案6】:

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

          我使用桥接模式来分离正交概念,它们都属于一个更大的概念——让它们独立变化。它通常涉及多个抽象。

          IMO,策略模式更简单或更扁平。它肯定适用于 OCP,但不一定是另一个更大的概念(如桥接模式)的一部分。

          【讨论】:

            【解决方案7】:

            对于策略模式,只有实现会有所不同。

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

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

            【讨论】:

              【解决方案8】:
              1. 策略模式用于行为决策,而桥梁模式用于结构决策。

              2. Brigde 模式将抽象元素与实现细节分开,而Strategy 模式关注的是让算法更具可互换性。

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

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

              【讨论】:

              • 为什么只有策略模式更“可互换”。由于我们对接口而不是实现进行编码,因此我们可以在策略或桥接中交换实现,正如您在代码示例中演示的那样,将StereoTV 交换,代码就可以工作了。
              【解决方案9】:

              我也是这么想的,但最近我不得不使用桥接,并意识到桥接是使用策略并将抽象添加到上下文中,以便您以后可以在不更改客户端的情况下进行更多更改。当使用没有抽象的 Strategy 时,设计没有那么灵活,并且可能需要稍后对客户端进行更改。但是当使用整个桥时,设计变得更加灵活。在这里,您可以看到从 Strategy 到 Bridge 如何提供更大的灵活性。我们还假设现在“visa”和“master”不仅可以在卡上使用,还可以在手机和芯片上使用;如果我们使用桥接,添加这种支持会容易得多。

              【讨论】:

                【解决方案10】:

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

                【讨论】:

                  【解决方案11】:

                  策略:

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

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

                  【讨论】:

                    【解决方案12】:

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

                    【讨论】:

                      【解决方案13】:

                      添加到 willcodejavaforfood 的答案中,它们在实现中可以是相同的。但是,您使用策略来交换诸如排序策略之类的策略,而使用桥接来桥接两个对象的实现,例如数据库包装器和网络适配器,以便客户端代码可以使用其中任何一个来处理相同的 API。所以命名实际上说明了一切

                      【讨论】:

                        【解决方案14】:

                        来自Strategy 模式上的 wiki

                        策略的 UML 类图 模式与图相同 桥模式。然而,这两个 设计模式在 他们的意图。而战略 模式是为了行为, 桥梁模式是为了结构。

                        上下文和上下文之间的耦合 策略比 抽象和之间的耦合 在 Bridge 中的实施 模式。

                        【讨论】:

                        • 你能详细说明最后一句话吗?
                        猜你喜欢
                        • 1970-01-01
                        • 2019-03-03
                        • 2010-10-11
                        • 2010-10-14
                        • 1970-01-01
                        • 2010-12-12
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多