设计模式记录3之“策略者模式”

今天学习了《大话设计模式》中的策略者模式。

定义:策略模式就是用来封装算法的。在实践中,我们用它来封装几乎任何类型的规则,只要在分析过程中听到任何时间有任何不同的应用规则,就可以考虑使用策略者模式处理这种变化的可能性。

优点:1 定义了一系列可重用的算法和行为,其中用到的继承有助于取出这些算法中的公共功能;

        2  简化了单元测试,每个类都是一个单独的算法,可以外接一个自己的接口进行测试。

场景: 一个商场的收银系统,有时候是"正常收费",有时候"打八折",有"满300减20"......各种收银的可能性都有。于是在这里我们就可以用到"策略模式"。

思路:定义一个接口,定义所有的算法的接口。创建各种算法(正常收费,打八折.....都是算法) ,继承算法接口,实现具体的算法方法。创建策略模式类,根据条件指定实现哪一个算法的实例。创建客户端,只需要传入参数即可。上代码:

 Step 1:

  ///   <summary>
    
///  策略者模式
    
///  定义算法接口
    
///   </summary>
     interface  InterfaceStrategy
    {
       
void  GetStrategy();
    }

step 2:

  ///   <summary>
    
///  算法A类继承接口
    
///   </summary>
     class  StrategyA:InterfaceStrategy
    {
        
public   void  GetStrategy()
        {
            Console.WriteLine(
" 继承了A类算法 " );
        }
    }

  
///   <summary>
    
///  算法B类,继承接口
    
///   </summary>
     class  StrategyB:InterfaceStrategy
    {
        
public   void  GetStrategy()
        {
            Console.WriteLine(
" 实现了B类算法 " );
        }
    }

 step 3: 

class  StrategyContext
    {
        InterfaceStrategy strategy 
=   null ; // 算法接口,定义在外层
         ///   <summary>
        
///  策略这模式与简单工厂模式相结合
        
///  根据调试决定实例化哪个算法
        
///   </summary>
         public  StrategyContext( string  type)
        {
            
switch  (type)
           { 
               
case   " A " :
                   StrategyA a 
=   new  StrategyA();
                   strategy 
=  a;
                   
break ;
               
case   " B " :
                   StrategyB b 
=   new  StrategyB();
                   strategy 
=  b;
                   
break ;
               
default :
                   
break ;
           }
        }

        
// 执行这个方法的时候,strategy对象已经通过switch分支语句获得了具体的行为对象
         public   void  GetStrategyResult()
        {
            strategy.GetStrategy();
        }

    }

 step 4:

///   <summary>
        
///  策略者模式
        
///  客户端
        
///   </summary>
        
///   <param name="args"></param>
         static   void  Main( string [] args)
        {
            
string  type = " A " ;
            
// 将算法参数传入StrategyContext中,构造函数实例化
            StrategyContext context  =   new  StrategyContext(type);
            context.GetStrategyResult();
            Console.ReadLine();
        }

 输出结果根据传入的参数"type"决定实例化哪个算法的实例。

到这里,我也跟书中小菜一样,觉得跟简单工厂一样,都是在switch语句中实现的,简单工厂是根据条件判断实例化那一个对象,策略者模式是根据条件判断实现哪一个算法。总觉得两者差不多。思考中?

---------

题外话:反射

MSDN介绍:

反射提供了封装程序集,模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有的对象获取类型并调用其方法或者访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。

 用静态方法GetType 从 Object基类派生的所有类型都继承该方法,获取变量类型的简单反射示例:

int  i  =   42 ;
System.Type type 
=  i.GetType();
System.Console.WriteLine(type);

输入为:
System.Int32

 使用反射获取已加载的程序集的完整名称:

System.Reflection.Assembly o  =  System.Reflection.Assembly.Load( " mscorlib.dll " );
System.Console.WriteLine(o.GetName());

输出为:
mscorlib, Version
= 2.0 . 0.0 , Culture = neutral, PublicKeyToken = b77a5c561934e089

 反射在策略模式中的应用:

对于以上的代码,需要改的有两个地方,一个地方是Step3,去掉繁琐的switch语句,用一个方法代替,上代码:

         ///   <summary>
        
///  利用反射机制
        
///   </summary>
         private  InterfaceStrategy infaceStrategy;
        
public   void  setBehavior(InterfaceStrategy super)
        {
            
this .infaceStrategy  =  super;
            super.GetStrategy();
        }

另一个也是反射应用的关键,step 4,客户端应用:

            // 利用反射机制实现 CreateInstance( " Strategy.StrategyB " ) 中的参数动态的获取实例
            StrategyContext context  =   new  StrategyContext();
            context.setBehavior((InterfaceStrategy)Assembly.Load(
" Strategy " ).CreateInstance( " Strategy.StrategyB " ));
            Console.ReadLine();

 这样的话输出结果是"实现了B类算法"。其中反射的重点是:

 

                  Assembly.Load("程序集名称").CreateInstance("命名空间.类名称")                    

 

 此处客户端我是为了简单才这样写的,其中 CreateInstance("Strategy.StrategyB")的参数"命名空间.类名称"中的类名称,存储在XML文件中,然后在客户端中读取出来,这样当我们要用用哪个算法的时候就只需要更改XML就可以了。

 XML文件如下:

<? xml version="1.0" encoding="utf-8"  ?>  
< CashAcceptType >
   
< type >
      
< name > A </ name >
      
< class > StrategyA </ class >
  
</ type >
     
< type >
     
< name > B </ name >
     
< class > StrategyB </ class >
  
</ type >
</ CashAcceptType >

你可能感兴趣的:(设计模式)