简体   繁体   中英

The Strategy design pattern vs simple Interface abstraction?

AFAIK , the strategy design pattern is pretty simple :

Interface :

public interface IStrategy
    {
        object DoAlgorithm(object data);
    }

Implementing classes :

lass ConcreteStrategyA : IStrategy
    {
        public object DoAlgorithm(object data)
        {
            var list = data as List<string>;
            list.Sort();
            return list;
        }
    }


 class ConcreteStrategyB : IStrategy
    {
        public object DoAlgorithm(object data)
        {
            var list = data as List<string>;
            list.Sort();
            list.Reverse();

            return list;
        }
    }

A context class which gets IStrategy in ctor :

class Context
    {

        private IStrategy _strategy;


        public Context(IStrategy strategy)
        {
            this._strategy = strategy;
        }

        public void SetStrategy(IStrategy strategy)
        {
            this._strategy = strategy;
        }

        public void DoSomeBusinessLogic()
        {
            ////
        }
    }

And of course , the Main method:

var context = new Context();
Console.WriteLine("Client: Strategy is set to normal sorting.");
context.SetStrategy(new ConcreteStrategyA());
context.DoSomeBusinessLogic();

Question:

OK , But how does it make any difference as opposed to :

Istrategy context = new ConcreteStrategyA (); //or ConcreteStrategyB
Console.WriteLine("Client: Strategy is set to normal sorting.");
context.DoSomeBusinessLogic();

Am I missing something ? why not just using interfaces?

You may need to do other things aside from the strategy... For example if you needed to add logging, or print statistics about your list - you probably wouldn't want to roll that into your strategy. You may also want to dynamically add or let the user choose strategies, for example by loading 'plugins'.

Generally you would use strategy for more short lived and volatile dependencies which may need to change, where as an interface would be used for larger or more static piece of functionality. The difference of for example runtime vs configuration flexibility.

To use your example of a List Sorter, the strategy may take an IEnumerable and sort it, but you may want to define additional functionality in the above ListSorter class that finally uses that strategy, for example taking different input collections and presenting them to the sorting strategy, or normalizing them somehow - in this way you decouple your code, as the component requesting the list be sorted doesn't care how the component ends up sorting it, and the sorting code doesn't need to know about the normalization etc. Of course this is more useful in larger applications and in combination with other techniques, so is hard to demonstrate in the trivial example like this, but hopefully gives you an idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM