策略与桥梁模式

Posted

技术标签:

【中文标题】策略与桥梁模式【英文标题】:Strategy vs. Bridge Patterns 【发布时间】:2011-08-17 08:06:51 【问题描述】:

我知道以前有人问过这个问题(例如,What is the difference between the bridge pattern and the strategy pattern?)。

但是,有人可以使用明确的示例解释有什么区别以及在什么情况下必须选择一个而不是另一个?更少的概念理论,更实际的“现实生活”场景将不胜感激。

【问题讨论】:

【参考方案1】:

策略:

    策略是行为设计​​模式。 If 用于在算法族之间切换。

    此模式包含一个抽象策略接口和该接口的许多具体策略实现(算法)。

    应用程序仅使用策略接口。根据某些配置参数,具体策略将被标记到接口

桥:

    它允许抽象和实现独立变化它使用组合而不是继承。 桥是一种结构模式

但是,有人可以用清晰的例子解释一下有什么区别以及在什么情况下必须选择一个而不是另一个?

请参阅以下帖子以深入了解策略和桥接模式的用例:

Real World Example of the Strategy Pattern

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

速记:

    使用 策略 模式通过将一种策略替换为另一种策略来动态更改实现。

    一个真实的例子:航空公司在非高峰月份提供折扣。只需在高峰时段将票价折扣策略更改为无折扣策略即可。

    在编译时还没有决定抽象和实现并且可以独立变化时,使用桥接模式

汽车行业的一个真实例子:不同类型的齿轮可以组装成不同类型的汽车CarGear 规范和实现都可以独立更改。

【讨论】:

我不明白这如何解决 OP 问题。 这两个嵌入式帖子包含真实世界的示例以及当前帖子中引用的差异。【参考方案2】:

桥接模式和策略模式的区别:

桥接模式使我们能够重新实施,根据我们当前的情况运行业务结构,另一方策略模式使我们能够实施各种业务策略并将它们封装起来并根据情况或一次使用它们。

两者的主要区别在于使用桥接模式我们可以改变我们的整体结构,但使用策略我们可以同时改变我们的业务策略。

根据我的理解,我在下面详细阐述了两个非常重要的设计模式。 请小心扔掉这个我想它会清除你对它们的理解。


桥接模式:

什么是桥接设计模式?

GoF 建议的桥模式的意义是将组件的实现与其抽象分离。

我们什么时候会使用桥接设计模式?

让我们想象一个组件已经实现并且根据您的业务需求运行良好的情况。突然,该组织改变了他们的商业战略。为此,您需要更改或重新实现组件。在这种情况下,您将做什么改变过去几年运行良好的前一个,或者您创建新组件。在这种情况下,桥模式很好地处理了这个场景。请参阅下面的示例以更好地理解。

// Main component
public interface Ibridge

    void function1();


// Already Implemented that are currently being using
public class Bridge1 : Ibridge 

    public void function1()
    
        Console.WriteLine("Implemented function from bridge 1");
    


//New Implementation as per Organisation needs
public class Bridge2 : Ibridge 

    public void function1()
    
        Console.WriteLine("Implemented function from bridge2");
    


//Abstract Calling functionalities
public interface IAbstractBridge  

    void CallFunc1();


// implementation of calling implemented component at a time
public class AbstractBridge:IAbstractBridge  

    protected Ibridge _ibridge;

    public Ibridge Ibridge
    
        set  _ibridge = value; 
    
    
    public void CallFunc1()
    
        this._ibridge.function1();
    

class Program

    static void Main(string[] args)
    
        AbstractBridge abp = new AbstractBridge();
        /*  
            here you see that now being using the previous implemented component.
            but need change newly implemented component so here we need just changed
            the implementation of component, please see below
        */
        //Commented old one
        abp.Ibridge = new Bridge1(); 
        
        //using new one just change the "Bridge1" to "Bridge2"
        abp.Ibridge = new Bridge2(); 
        
        abp.CallFunc1();
    


策略设计模式:

什么是策略设计模式?

GoF 建议的策略模式的意义是定义一系列算法,封装每个算法,并使它们可互换。策略让算法独立于使用它的客户端而变化。

我们什么时候会使用策略设计模式?

假设一个购物中心的老板想要吸引顾客根据他们的不同场合提供不同的折扣优惠,并且任何时候老板都可以从折扣模式切换到正常模式,反之亦然,那么如何处理这种情况在这种情况下,策略模式处理了这种情况。让我们看下面的例子来更好地理解。

所有策略
public interface ISellingStrategy

    void selling();

      
public class BasicStrategy : ISellingStrategy

    public void selling()
    
        Console.WriteLine("Buy Three get 5% discount.");
    


public class ChrismasStrategy : ISellingStrategy

    public void selling()
    
        Console.WriteLine("Buy Three get one offer + extra 5% discount.");
    


public class HoliFestiveStrategy : ISellingStrategy

    public void selling()
    
        Console.WriteLine("Buy two get one offer + extra 5% discount.");
    


public class DurgapuljaStrategy : ISellingStrategy

    public void selling()
    
        Console.WriteLine("Buy one get one offer + extra 5% discount.");
    

结算
public class Billing

    private ISellingStrategy strategy;
    public void SetStrategy(ISellingStrategy _strategy)
    
        this.strategy = _strategy;
    

    public void ApplyStrategy()
    
        strategy.selling();
        Console.WriteLine("Please wait offer is being applying...");
        Console.WriteLine("Offer is now Applied and ready for billing..");

    


创建计费类对象的工厂模式
 public class BillingFactory
 
     public static Billing CreateBillingObject()
     
         return new Billing();
     
 
通话
class Program

    static void Main(string[] args)
    
        Billing billing = BillingFactory.CreateBillingObject();
        billing.SetStrategy(new BasicStrategy());
        billing.ApplyStrategy();

        Console.ReadLine();
    

【讨论】:

在回答“桥接模式和策略模式有什么区别?”这个问题时,传统上会以某种方式提及策略模式。另外,请阅读formatting guidelines【参考方案3】:

我可以说这很难解释。许多使用它并理解它的人很难向新手解释它。

对于像我这样喜欢类比思考的人:

策略模式

所以战略是一种一维的概念。考虑一个可供选择的一维策略数组。

示例 1:管道工的工具

策略模式就像一个管道工,他拥有各种工具来疏通管道。每次工作都是一样的;这是为了疏通管道。但他选择完成这项工作的工具可能会因情况而异。也许他会尝试一个,如果这不起作用,他会尝试另一个。

在这个类比中,“疏通管道”是实现策略之一的方法。 Snake Brush、Power Auger 和 Draino 是具体的策略,而管道工是包含该方法的类(在大多数图中标记为“Context”)。

示例 2:多头螺丝刀

或者您可以想到多位螺丝刀上的可互换位。 它们旨在在运行时进行更改以适应手头的工作,即搞砸一些事情。

桥接模式

所以桥是一个二维的概念。考虑一维(行)是需要实现的方法列表,而第二维(列)是将实现这些方法中的每一个的实施者。

示例 1:应用和设备

桥接模式就像一个人可以通过多种方式进行交流(电子邮件、文本、谷歌语音、电话、Skype)和许多可以通过这些方式进行交流的设备 - PC、平板电脑、和智能手机。

各种通信方式(电子邮件、文本、电话)将是抽象接口上的方法,我们称之为“CommunicationDevice”。在此模式中,CommunicationDevice 是实现者。这个类比中的每个设备(PC、平板电脑、智能手机)都是实现所有这些方法(电子邮件、文本、电话)的 ConcreteImplementor。

示例 2:odbc 数据库驱动程序和 odbc 函数

另一个现成的桥接示例是 Windows 的 odbc 或 oledb 数据库驱动程序模块。它们都在相同的标准“数据库驱动程序”接口上实现了各种方法,但它们以不同的方式实现该接口。即使您使用的是同一个数据库,比如 Sql Server,仍然有不同的驱动程序可以与 Sql Server 进行通信,尽管在幕后以不同的方式。

示例 3:实现者(列)实现方法(行)

【讨论】:

我非常喜欢这个答案,但是我不明白示例2的数字......它与ODBC甚至数据库无关。【参考方案4】:

策略模式封装了算法,因此它们可以在复杂的程序中使用和更改(不会弄乱工作),而桥接模式允许两个接口松散绑定,以便它们可以交互,但可以相互独立地更改。

您可以在此处找到桥接和策略模式的 php 示例:

http://www.php5dp.com/category/design-patterns/bridge/

http://www.php5dp.com/category/design-patterns/strategy/

您会发现很多对这两种模式都有帮助的示例。

【讨论】:

【参考方案5】:

两种模式都将接口与实现分开。我认为关键的区别在于桥模式使用继承(“is a”),而策略模式使用组合(“has a”)。

桥梁模式:

class Sorter abstract
 
   virtual void Sort() = 0;


// MergeSorter IS A Sorter
class MergeSorter : public Sorter

   virtual void Sort() override;

策略模式:

class SortStrategy abstract

   virtual void Sort() = 0;


// Sorter HAS A SortStrategy
class Sorter
 
   Sorter(SortStragety *strategy) : mStrat(strategy) 

   void Sort() mStrat->Sort();

   SortStrategy *mStrat;

【讨论】:

【参考方案6】:

桥模式告诉如何组织类,策略——如何组织算法。

【讨论】:

【参考方案7】:

桥接模式对抽象和实现进行了区分,使得两者可以独立变化。我将使用来自

的示例

Java 中的模式,第 1 卷:使用 UML 说明的可重用设计模式目录,第二版

您需要提供访问物理传感器的类,例如在秤、速度测量设备等中找到的传感器。每个传感器都会产生一个数字,但数字可能意味着不同的东西。对于秤来说,它可能意味着重量,对于速度测量装置,它可能意味着速度。

因此,您可以首先创建一个 Sensor 抽象类来表示所有传感器之间的共性以及不同类型传感器的各种子类。这是一个稳健的设计,允许您在未来提供更多类型的传感器。

现在假设传感器由不同的制造商提供。您必须为制造商 X 和制造商 Y 创建一个传感器类的层次结构。现在的问题是客户需要知道制造商之间的区别。如果您决定支持第三家制造商...?

解决方案是提供主要的抽象层次结构,即。 Sensor 抽象类和 SpeedSensor 和 WeightSensor 等子类。然后提供将存在于抽象和实现之间的接口(桥)。所以会有一个 SensorInterface、WeightSensorInterface 和 SpeedSensorInterface,它们规定了每个具体的传感器类必须提供的接口。抽象不知道实现,而是知道接口。最后,您可以为每个制造商创建一个 concreate 实现。即 XSensor、XWeightSensor 和 XSpeedSensor、YSensor、YSpeedSensor 和 YWeightSensor。

客户端仅依赖于抽象,但可以插入任何实现。因此在此设置中,可以在不更改任何具体类的情况下更改抽象,并且可以更改实现而不用担心抽象。

如您所见,这描述了一种构建类的方法。

另一方面,策略关注的是在运行时改变对象的行为。我喜欢使用一个角色拥有几种不同类型武器的游戏示例。角色可以攻击,但攻击的行为取决于角色当时持有的武器,这在编译时无法得知。

因此,您可以使武器行为可插入,并根据需要将其注入角色中。因此是一种行为模式。

这两种模式解决了不同的问题。该策略关注于使算法可互换,而 Bridge 关注于将抽象与实现分离,以便您可以为同一抽象提供多个实现。也就是说,桥与整个结构有关。

以下是一些可能有用的链接:

    Bridge Pattern Strategy Pattern

【讨论】:

【参考方案8】:

策略模式

此模式允许执行的算法独立于使用它的客户端而变化。即,它允许在运行时动态选择许多算法中的一个,而不是让固定算法针对给定的情况执行。这涉及从其宿主类中删除一个算法并将其放入一个单独的类中。

例如,假设一个人想从一个城市旅行到另一个城市,那么他有几个选择:坐公共汽车、租车、搭火车等。所以选择的每种交通方式都会演变成一个单独的算法来被执行。选择的运输方式将取决于运行时决定的各种因素(成本、时间等)。换句话说,选择执行的策略将即时决定。

另一个例子,假设一个人想要实现一个SortedList 类(主控制器),该类Sorts 基于strategy。策略是一种用于排序的方法(如 MergeSort、QuickSort)。

与桥模式比较

主要区别(即使两种模式具有相同的 UML)是与桥模式(结构模式)不同,策略模式是行为模式。结构模式建议对象组合或关联或继承以形成更大对象的方式,即它们专注于对象组合。而行为模式处理算法或业务逻辑(而不是对象创建本身),即它们关注对象之间的协作。

请注意,大多数算法可以实现为静态或单例类,只需要创建单个实例(即,每次设置策略时都不会调用new)。

仔细观察这两种模式的实现会发现,在桥接模式中,一个是创建对象的具体实现,然后是调用。

// Set implementation and call
// i.e. Returns (creates) the concrete implementation of the object, 
// subsequently operation is called on the concrete implementation
ab.Implementor = new ConcreteImplementorA(); 
ab.Operation();

而在策略模式的情况下,人们不会直接使用算法的具体实现,而是创建策略应该执行的上下文,

// Set the context with a strategy
// i.e. Sets the concrete strategy into the context, concrete implementation of the class not 
// directly available as a data object (only the algorithm is available).    
context = new Context (new ConcreteStrategyA());     
context.contextInterface();

// Strategy can be reused instead of creating a new instance every time it is used.
// Sort example
MergeSort mergeSort = new MergeSort();
QuickSort quickSort = new QuickSort();
...
context = new Context (mergeSort);
context.Sort();
...
context = new Context (quickSort);
context.Sort();
...
context = new Context (mergeSort);
context.Sort();

【讨论】:

这里还是很迷茫。我是否理解唯一的区别是 Bridge 实例化了不同算法的具体实现者? @S. Valmont,桥模式的对象returned(创建)是调用Operation()的对象,而在策略模式的情况下,创建的对象无关紧要,而算法(或行为)很重要。随后,具体的Strategy实现在访问operationSort())时不会暴露; 正如@vpit3833 所指出的,Bridge pattern does not aim to export anything outside the project/application itself. Whereas, exporting the functions/methods/API appears to be the main aim for strategy pattern【参考方案9】:

让我背诵链接问题的答案。

桥接模式是一种结构模式,也就是说,它列出了如何构建项目组件的想法。它用于隐藏两个抽象级别。 Wikipedia (http://en.wikipedia.org/wiki/Bridge_pattern) 上的示例代码用最明确的术语解释了它。

策略模式是一种动态模式。当任何野函数都可以实现需求时,就会使用策略模式。示例可以是任何允许开发和安装插件的程序。在 Wikipedia pageg(http://en.wikipedia.org/wiki/Strategy_pattern) 上,ConcreteStrategyAdd、ConcreteStrategySubtract 等是用于 ConcreteStrategy 类的插件。那里可以使用任何实现接口 Strategy 的方法。

【讨论】:

我发现***的例子最模棱两可。它似乎只不过是一个调用可变策略的可变容器类。我仍然不知道这如何或为什么需要一个名称不同于“策略”的单独模式。 桥接模式并不旨在导出项目/应用程序本身之外的任何内容。而导出函数/方法/API 似乎是策略模式的主要目标。因此,前者是结构模式,后者是动态模式。据我了解,到目前为止。

以上是关于策略与桥梁模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 模式PK:策略模式VS桥梁模式

设计模式 桥梁模式 JDBC

桥梁模式

入门设计模式之桥梁

设计模式之桥梁模式

设计模式-桥梁模式