Search code examples
c#design-patternsstrategy-pattern

Strategy pattern movies conditionals from inside the main class to the client code, so what's the point?


I am trying to understand the strategy pattern, here is an example, we have a Customer that has a method GetDiscount, this method is written as follows

GetDiscount
    If (Condition1)
        Return 10%
    else (Condition2)
        Return 20%

Now I have refactored the code using the strategy pattern so it becomes

GetDiscount
     Invoke the attached strategy

And we create two strategy class 10%Strategy and 20%Strategy to encapsulate the behavior of the discount

And for the client code to use the customer class it becomes

c = new Customer

if(condition1)
c.attach(10%Strategy)
else (condition2)
c.attach(20%Strategy)

c.GetDiscount

So as you can see we have moved the conditionals from inside Customer class into the client code, not only this, but this conditional branching itself is considered a business logic and we let it to leak into client code that might be a presentation controller for example.

Am I missing something?


Solution

  • In large software systems developed with object-oriented techniques you have code that assembles objects, and code that uses the assembled objects. In your case, the code that calls attach is assembling Customer object for later use, and the code that calls GetDiscount is one that makes use of the object.

    The goal the strategy pattern fulfills is moving the decision of which discount the Customer gets form the point where the object is used to the point where the object is assembled. The condition remains in your code, but it is now confined to the place where you create your Customer object.

    Once the assembly is done, the Customer object becomes self-sufficient. The data that you used to compute the condition for 10% or 20% discount is no longer required, because it is embedded in the type of discount. The logic for computing a discount follows the Customer into different places in code. You can use discount computation without duplicating the logic in multiple places - for example, to compute the total price of sale, to preview the price of an individual item, to process a return, and so on. This also saves you from duplicating the same logic when the computation is needed more than once.