C++ Programmer's Cookbook

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}

模式设计c#--行为型--strategy

名称 Strategy
结构 o_strategy.bmp
意图 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性
  • 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
  • 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
  • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  • 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。

namespace  Strategy_DesignPattern
{
    
using  System;

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


    
class  FirstStrategy : Strategy 
    
{
        
override   public   void  DoAlgorithm()
        
{
            Console.WriteLine(
" In first strategy " );            
        }

    }


    
class  SecondStrategy : Strategy 
    
{
        
override   public   void  DoAlgorithm()
        
{
            Console.WriteLine(
" In second strategy " );            
        }

    }


    
class  Context 
    
{
        Strategy s;
        
public  Context(Strategy strat)
        
{
            s 
=  strat;            
        }


        
public   void  DoWork()
        
{
            
//  some of the context's own code goes here
        }


        
public   void  DoStrategyWork()
        
{
            
//  now we can hand off to the strategy to do some 
            
//  more work
            s.DoAlgorithm();
        }

    }


    
///   <summary>
    
///     Summary description for Client.
    
///   </summary>

     public   class  Client
    
{
        
public   static   int  Main( string [] args)
        
{    
            FirstStrategy firstStrategy 
=   new  FirstStrategy();
            Context c 
=   new  Context(firstStrategy);
            c.DoWork();
            c.DoStrategyWork();

            
return   0 ;
        }

    }

}


一、 策略(Strategy)模式

策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

假设现在要设计一个贩卖各类书籍的电子商务网站的购物车(Shopping Cat)系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的教材类图书实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣,而对非教材类的计算机图书有3%的折扣;对其余的图书没有折扣。由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。

使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略类(ConcreteStrategy)中提供。由于算法和环境独立开来,算法的增减、修改都不会影响环境和客户端。当出现新的促销折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可。策略模式相当于"可插入式(Pluggable)的算法"。
 何时使用何种具体策略角色

在学习策略模式时,学员常问的一个问题是:为什么不能从策略模式中看出哪一个具体策略适用于哪一种情况呢?

答案非常简单,策略模式并不负责做这个决定。换言之,应当由客户端自己决定在什么情况下使用什么具体策略角色。策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中"退休"的方便,策略模式并不决定在何时使用何种算法。
sort()很好的例子:

//  Strategy pattern -- Real World example  
using  System;
using  System.Collections;

//  "Strategy"
abstract   class  SortStrategy
{
  
//  Methods
   abstract   public   void  Sort( ArrayList list );
}


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

}


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

}


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

}


//  "Context"
class  SortedList
{
  
//  Fields
   private  ArrayList list  =   new  ArrayList();
  
private  SortStrategy sortstrategy;

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


  
//  Methods
   public   void  Sort()
  
{
    sortstrategy.Sort( list );
  }


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


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

}


/**/ ///   <summary>
///  StrategyApp test
///   </summary>

public   class  StrategyApp
{
  
public   static   void  Main(  string [] args )
  
{
    
//  Two contexts following different strategies
    SortedList studentRecords  =   new  SortedList( );
    studentRecords.Add( 
" Samual "  );
    studentRecords.Add( 
" Jimmy "  );
    studentRecords.Add( 
" Sandra "  );
    studentRecords.Add( 
" Anna "  );
    studentRecords.Add( 
" Vivek "  );

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

}

六、 在什么情况下应当使用策略模式

在下面的情况下应当考虑使用策略模式:

1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

2. 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。

3. 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。

4. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。


七、 策略模式的优点和缺点

策略模式有很多优点和缺点。它的优点有:

1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免重复的代码。

2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。

3. 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。

策略模式的缺点有:

1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。

2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。


八、 其它

策略模式与很多其它的模式都有着广泛的联系。Strategy很容易和Bridge模式相混淆。虽然它们结构很相似,但它们却是为解决不同的问题而设计的。Strategy模式注重于算法的封装,而Bridge模式注重于分离抽象和实现,为一个抽象体系提供不同的实现。Bridge模式与Strategy模式都很好的体现了"Favor composite over inheritance"的观点。

posted on 2006-01-03 16:17 梦在天涯 阅读(984) 评论(0)  编辑 收藏 引用 所属分类: Design pattern


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

EMail:itech001#126.com

导航

统计

  • 随笔 - 461
  • 文章 - 4
  • 评论 - 746
  • 引用 - 0

常用链接

随笔分类

随笔档案

收藏夹

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

积分与排名

  • 积分 - 1792324
  • 排名 - 5

最新评论

阅读排行榜