开发者

Strategy vs. Bridge Patterns

I know this question's been asked before (e.g., What is the difference between the bridge pattern and the strategy pattern?).

However, could someone please explain, using clear-cut examples, what the differ开发者_JAVA百科ence is and in what sorts of cases one must be selected over the other? Less conceptual theory, more practical "real-life" scenarios would be appreciated.


The Bridge Pattern makes a distinction between an abstraction and an implementation in such a way that the two can vary independently. I will use the example from

Patterns in Java, Volume 1: A Catalog of Reusable Design Patterns Illustrated with UML, Second Edition

You need to provide classes that access physical sensors such as found in scales, speed measuring devices etc. Each sensor produces a number but the number could mean different things. For the scale it could mean the weight and for the speed measuring device it may mean speed.

So you can start by creating a Sensor abstract class to represent the commonality between all sensors and various subclasses for the different types of sensors. This is a robust design allowing you to provide many more types of sensors in the future.

Now suppose that sensors are provided by different manufacturers. You will have to create a heirarchy of sensor classes for manufacturer X and another for manufacturer Y. The problem now is that the clients would need to know the difference between the manufacturers. And if you decide to support a third manufacturer...?

The solution is to provide the main abstraction heirarchy, ie. the Sensor abstract class and sub classes such as SpeedSensor and WeightSensor and so on. Then provide the interface (Bridge) that will exist between the abstraction and the implementation. So there will be a SensorInterface, WeightSensorInterface and SpeedSensorInterface, which dictates the interface that each concrete sensor class must provide. The abstraction does not know about the implementation, rather it knows about the interface. Finally, you can create an concreate implementation for each manufacturer. That is, XSensor, XWeightSensor and XSpeedSensor, YSensor, YSpeedSensor and YWeightSensor.

Clients depend only on the abstraction but any implementation could be plugged in. So in this setup, the abstraction could be changed without changing any of the concrete classes, and the implementation could be changed without worrying about the abstraction.

As you can see this describes a way to structure your classes.

The Strategy on the other hand is concerned with changing the behaviour of an object at run time. I like to use the example of a game with a character that possesses several different types of weapons. The character can attack but the behaviour of attack depends on the weapon that the character is holding at the time, and this cannot be known at compile time.

So you make the weapon behaviour pluggable and inject it into the character as needed. Hence a behavioral pattern.

These two patterns solve different problems. The strategy is concerned with making algorithms interchangeable while the Bridge is concerned with decoupling the abstraction from the inplementation so that you can provide multiple implementations for the same abstraction. That is, the bridge is concerned with entire structures.

Here are a few links that might be useful:

  1. Bridge Pattern
  2. Strategy Pattern


I can tell this is hard to explain. Many people who use it and understand it have a hard time explaining it to newbies.

For those like me who think in terms of analogies:

Strategy Pattern

So strategy is kind-of a one-dimensional concept. Think of a one-dimensional array of strategies to choose from.

Example 1: Plumber's tools

The strategy pattern is like a plumber who has various tools to get a pipe unclogged. The job is the same each time; it's to unclog the pipe. But the tool he chooses to get this done can vary depending on the situation. Maybe he'll try one and if that doesn't work he'll try another.

In this analogy, "unclog the pipe" is the method that will implement one of the strategies. Snake brush, power auger, and draino are the concrete strategies, and the plumber is the class containing the method (labeled "Context" in most diagrams).

Strategy vs. Bridge Patterns

Example 2: Multi-bit screwdriver

Or you could think of the interchangeable bits on a multi-bit screwdriver. They are meant to be changed out at run-time to suit the job at hand, which is to screw something.

Strategy vs. Bridge Patterns

Bridge Pattern

So bridge is a two-dimensional concept. Think of one dimension (the rows) being the list of methods that need to be implemented, and the second dimension (the columns) being the Implementors who will implement each one of those methods.

Example 1: Apps and devices

The bridge pattern is like a person that has many ways that they can communicate (email, text, google voice, phone, skype) and many devices on with which they can communicate in these various ways - a PC, a tablet, and a smart phone.

The various ways to communicate (email, text, phone) would be the methods on an abstract interface, let's call it "CommunicationDevice". In this pattern, CommunicationDevice is the Implementor. Each device in this analogy (PC, tablet, smart phone) is the ConcreteImplementor that implements all these methods (email, text, phone).

Strategy vs. Bridge Patterns

Example 2: Odbc database drivers and odbc functions

Another ready example of bridge is the odbc or oledb database driver modules from Windows. They all implement the various methods on the same standard "database driver" interface, but they implement that interface in different ways. Even if you are using the same database, say Sql Server, there are still different drivers that can talk to Sql Server, albeit in different ways under the covers.

Example 3: Implementors (columns) implementing methods (rows)

Strategy vs. Bridge Patterns


Strategy pattern

This pattern lets the algorithm that executes vary independently from the clients that use it. i.e. Instead of having a fixed algorithm to exeucte for a given sitaution, it allows one among many algorithms to be selected on-the-fly at runtime. This involves removing an algorithm from its host class and putting it in a separate class.

For example, suppose one wants to travel from a city to another, then he has several choices: take a bus, hire a car, catch a train, etc. So each mode of transport selected would transpire into a separate algorithm to be executed. The mode of transport chosen will depend on various factors decided at runtime (cost, time, etc.). In other words, the strategy chosen to execute will be decided on-the-fly.

Another example, suppose one wants to implement a SortedList class(main controller) that Sorts based on a strategy. The strategy is the method that one uses to sort (like MergeSort, QuickSort).

Comparison with the Bridge pattern

The main difference (even though both patterns have the same UML) is that unlike the bridge pattern (which is a structural pattern), the strategy pattern is a behavioral pattern. Structural patterns suggest ways in which objects are composed or associated or inherited to forms larger objects i.e. they focus on object composition. While behavioral patterns deal with the algorithm or business logic (and not on the object creation itself) i.e. they focus on the collaboration between objects.

Note that most algorithms can be implementated as static or singleton classes required only single instance creation (i.e. new is not called for everytime a strategy is set).

A closer look at the implementation of the two patterns will reveal that in the bridge pattern one creates the concrete implementation of the object and then the call.

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

Whereas in the case of the strategy pattern, one will not use the concrete implementation of the algorithm directly, instead he will create the context in which the strategy should execute,

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


The Bridge pattern tells how organize classes, the Strategy - how organize algorithms.


Difference between bridge and strategy pattern:

Bridge pattern gives us the ability to re implement, being running business structure as per our current situation , other side strategy pattern gives us ability to implement our various business strategy and encapsulate them and use them as per situation or at a time.

Main difference between both is using bridge pattern we can change our whole structure but using strategy we are able to change our business strategy parallelly.

I have elaborated two very important design patter below as per my understanding. please carefully go throw this i think it will clear your understanding about both them.


Bridge Pattern:

What is Bridge Design Pattern?

The sense of GoF suggested Bridge pattern is decouple the implementation of an component from it's abstraction.

When we will use the Bridge Design Pattern?

Let imagine a situation where a component already implemented, and it's running well as per your business need. Suddenly the organisation changed their business strategy. For this you need to be change or re-implemented the component. At this situation, what you will do change the previous one that are running well last few years, or you Create the new component. At this situation bridge pattern beautifully handled the scenario. See the example below for better understanding.

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

Strategy design Pattern:

What is Strategy Design Pattern?

The sense of GoF suggested Strategy pattern is Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

When we will use the Strategy Design Pattern?

Let imagine a situation where a owner of shopping complex want to attract customer giving different discount offer based on their various occasion and the discount offer any time owner can switch from discount mode to normal mode vice versa ,then how to handle this situation At this situation strategy pattern handled the scenario. Lets See the example below for better understanding.

  • All Strategy:
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.");
    }
}
  • Billing:
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..");

    }

}
  • Factory patter for Creating Object of Billing Class
 public class BillingFactory
 {
     public static Billing CreateBillingObject()
     {
         return new Billing();
     }
 }
  • Calling
class Program
{
    static void Main(string[] args)
    {
        Billing billing = BillingFactory.CreateBillingObject();
        billing.SetStrategy(new BasicStrategy());
        billing.ApplyStrategy();

        Console.ReadLine();
    }
}


Both patterns separate interface from implementation. I think the key distinction is that the Bridge Pattern uses inheritance ("is a") while the Strategy Pattern uses composition ("has a").

Bridge Pattern:

class Sorter abstract
{ 
   virtual void Sort() = 0;
}

// MergeSorter IS A Sorter
class MergeSorter : public Sorter
{
   virtual void Sort() override;
}

Strategy Pattern:

class SortStrategy abstract
{
   virtual void Sort() = 0;
}

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

   void Sort() {mStrat->Sort();}

   SortStrategy *mStrat;
}


The Strategy pattern encapsulates algorithms so that they can be used and changed in a complex program (without gumming up the works) and the Bridge pattern allows two interfaces loosely bound so that they can interact but be changed independently of one another.

You can find PHP examples of the Bridge and Strategy patterns here:

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

and

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

You'll find a lot of examples for both patterns that may be helpful.


Strategy:

  1. Strategy is behavioral design pattern. If is used to switch between family of algorithms.

  2. This pattern contains one abstract strategy interface and many concrete strategy implementations (algorithms) of that interface.

  3. The application uses strategy interface only. Depending in some configuration parameter, the concrete strategy will be tagged to interface.

Bridge:

  1. It allows both abstractions and implementations to vary independently.
  2. It uses composition over inheritance.
  3. Bridge is a structural pattern.

However, could someone please explain, using clear-cut examples, what the difference is and in what sorts of cases one must be selected over the other?

Refer to below post to get insight on use cases of Strategy and Bridge patterns:

Real World Example of the Strategy Pattern

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

On quick note:

  1. Use Strategy pattern to dynamically change the implementation by replacing one strategy with other strategy.

    One real word example : Airlines offering discounts during off-peak months. Simply change fare discount strategy with no-discount strategy during high peak time.

  2. Use Bridge pattern when Abstractions and implementations have not been decided at compile time and can vary independently

One real world example in Automobile industry : Different type of Gears can be assembled into different types of Cars. Both Car and Gear specification and implementation can change independently.


Let me recite the answers from the linked question.

The bridge pattern is a structural pattern, that is, it lays out ideas of how to build a component of your project. It is used to hide two levels of abstractions. The sample code on Wikipedia (http://en.wikipedia.org/wiki/Bridge_pattern) explains it in most unambiguous terms.

The strategy pattern is a dynamic pattern. When any wild function can implement the requirements, a strategy pattern is used. Examples can be any program that allows for plugins to be developed and installed. On the Wikipedia pageg(http://en.wikipedia.org/wiki/Strategy_pattern), ConcreteStrategyAdd, ConcreteStrategySubtract, etc is plugin used in the ConcreteStrategy class. Any method could be used there that implements the interface Strategy.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜