设计模式之strategy策略模式

来源:互联网 发布:php array 清空 编辑:程序博客网 时间:2024/06/06 08:35
 

意图intent:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

适用性:

  • 许多相关的类仅仅是行为有异。策略提供了一种用多个行为中的一个行为来配置一个类的方法。
  • 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[H087] ,可以使用策略模式。
  • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  • 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

Definition

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

participants

    The classes and/or objects participating in this pattern are:

  • Strategy  (SortStrategy)
    • declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy
  • ConcreteStrategy  (QuickSort, ShellSort, MergeSort)
    • implements the algorithm using the Strategy interface
  • Context  (SortedList)
    • is configured with a ConcreteStrategy object
    • maintains a reference to a Strategy object
    • may define an interface that lets Strategy access its data.

对象可能经常需要使用多种不同的算法,但是如果变化频繁,会将类型变得脆弱。。。在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?

Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。所谓封装算法,支持算法的变化。Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要strategy模式。与state类似,如果strategy对象没有实例变量,那么各个上下文可以共享同一个strategy对象,从而节省对象开销。

 

Sample code in c#

This structural code demonstrates the Strategy pattern which encapsulates functionality in the form of an object. This allows clients to dynamically change algorithmic strategies.

// Strategy pattern -- Structural example

 

using System;

namespace DoFactory.GangOfFour.Strategy.Structural
{
  
  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      Context context;

      // Three contexts following different strategies
      context = new Context(new ConcreteStrategyA());
      context.ContextInterface();

      context = new Context(new ConcreteStrategyB());
      context.ContextInterface();

      context = new Context(new ConcreteStrategyC());
      context.ContextInterface();

      // Wait for user
      Console.Read();
    }
  }

  // "Strategy"

  abstract class Strategy
  {
    public abstract void AlgorithmInterface();
  }

  // "ConcreteStrategyA"

  class ConcreteStrategyA : Strategy
  {
    public override void AlgorithmInterface()
    {
      Console.WriteLine(
        "Called ConcreteStrategyA.AlgorithmInterface()");
    }
  }

  // "ConcreteStrategyB"

  class ConcreteStrategyB : Strategy
  {
    public override void AlgorithmInterface()
    {
      Console.WriteLine(
        "Called ConcreteStrategyB.AlgorithmInterface()");
    }
  }

  // "ConcreteStrategyC"

  class ConcreteStrategyC : Strategy
  {
    public override void AlgorithmInterface()
    {
      Console.WriteLine(
        "Called ConcreteStrategyC.AlgorithmInterface()");
    }
  }

  // "Context"

  class Context
  {
    Strategy strategy;

    // Constructor
    public Context(Strategy strategy)
    {
      this.strategy = strategy;
    }

    public void ContextInterface()
    {
      strategy.AlgorithmInterface();
    }
  }
}

 

Output

Called ConcreteStrategyA.AlgorithmInterface()

Called ConcreteStrategyB.AlgorithmInterface()

Called ConcreteStrategyC.AlgorithmInterface()

 

This real-world code demonstrates the Strategy pattern which encapsulates sorting algorithms in the form of sorting objects. This allows clients to dynamically change sorting strategies including Quicksort, Shellsort, and Mergesort.

// Strategy pattern -- Real World example

 

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Strategy.RealWorld
{
  
  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      // Two contexts following different strategies
      SortedList studentRecords = new SortedList();

      studentRecords.Add("Samual");
      studentRecords.Add("Jimmy");
      studentRecords.Add("Sandra");
      studentRecords.Add("Vivek");
      studentRecords.Add("Anna");

      studentRecords.SetSortStrategy(new QuickSort());
      studentRecords.Sort();

      studentRecords.SetSortStrategy(new ShellSort());
      studentRecords.Sort();

      studentRecords.SetSortStrategy(new MergeSort());
      studentRecords.Sort();

      // Wait for user
      Console.Read();
    }
  }

  // "Strategy"

  abstract class SortStrategy
  {
    public abstract void Sort(ArrayList list);
  }

  // "ConcreteStrategy"

  class QuickSort : SortStrategy
  {
    public override void Sort(ArrayList list)
    {
      list.Sort(); // Default is Quicksort
      Console.WriteLine("QuickSorted list ");
    }
  }

  // "ConcreteStrategy"

  class ShellSort : SortStrategy
  {
    public override void Sort(ArrayList list)
    {
      //list.ShellSort(); not-implemented
      Console.WriteLine("ShellSorted list ");
    }
  }

  // "ConcreteStrategy"

  class MergeSort : SortStrategy
  {
    public override void Sort(ArrayList list)
    {
      //list.MergeSort(); not-implemented
      Console.WriteLine("MergeSorted list ");
    }
  }

  // "Context"

  class SortedList
  {
    private ArrayList list = new ArrayList();
    private SortStrategy sortstrategy;

    public void SetSortStrategy(SortStrategy sortstrategy)
    {
      this.sortstrategy = sortstrategy;
    }

    public void Add(string name)
    {
      list.Add(name);
    }

    public void Sort()
    {
      sortstrategy.Sort(list);

      // Display results
      foreach (string name in list)
      {
        Console.WriteLine(" " + name);
      }
      Console.WriteLine();
    }
  }
}

 

Output

QuickSorted list

 Anna

 Jimmy

 Samual

 Sandra

 Vivek

 

ShellSorted list

 Anna

 Jimmy

 Samual

 Sandra

 Vivek

 

MergeSorted list

 Anna

 Jimmy

 Samual

 Sandra

 Vivek

 

原创粉丝点击