策略模式
The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
个人理解:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
该模式的解决方案:
策略模式涉及到三个角色
1:抽象策略(Strategy)角色:
定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。
2:环境(Context)角色:
2.1需要使用ConcreteStrategy提供的算法。
2.2内部维护一个Strategy的实例。
2.3负责动态设置运行时Strategy具体的实现算法。
2.4负责跟Strategy之间的交互和数据传递。
3:具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
实现了Strategy定义的接口,提供具体的算法实现。
应用场景:
多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyBehavior和QuackBehavior)
需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyBehavior和QuackBehavior的具体实现可任意变化或扩充)
对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。
优点:
提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
对于Strategy模式来说,
缺点:
因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
类图
代码
{
void Insert();
void UpDate();
void Select();
void Delete();
}
public class SqlServer : ISQL
{
public void Insert() { }
public void UpDate() { }
public void Select() { }
public void Delete() { }
}
public class Oracle : ISQL
{
public void Insert() { }
public void UpDate() { }
public void Select() { }
public void Delete() { }
}
public class Context
{
private ISQL _sql;
public Context(ISQL sql)
{
_sql = sql;
}
public void Insert()
{
_sql.Insert();
}
public void UpDate()
{
_sql.UpDate();
}
public void Select()
{
_sql.Select();
}
public void Delete()
{
_sql.Delete();
}
}
//调用
Bll.Strategy.Context context = new Bll.Strategy.Context(new Bll.Strategy.SqlServer());
context.Insert();
context.UpDate();
context.Select();
context.Delete();
.NET框架里的应用
public virtual void Sort (IComparer comparer)
2using System.Collections;
3
4public class SamplesArrayList {
5
6 public class myReverserClass : IComparer {
7
8 // Calls CaseInsensitiveComparer.Compare with the parameters reversed.
9 int IComparer.Compare( Object x, Object y ) {
10 return( (new CaseInsensitiveComparer()).Compare( y, x ) );
11 }
12
13 }
14
15 public static void Main() {
16
17 // Creates and initializes a new ArrayList.
18 ArrayList myAL = new ArrayList();
19 myAL.Add( "The" );
20 myAL.Add( "quick" );
21 myAL.Add( "brown" );
22 myAL.Add( "fox" );
23 myAL.Add( "jumps" );
24 myAL.Add( "over" );
25 myAL.Add( "the" );
26 myAL.Add( "lazy" );
27 myAL.Add( "dog" );
28
29 // Displays the values of the ArrayList.
30 Console.WriteLine( "The ArrayList initially contains the following values:" );
31 PrintIndexAndValues( myAL );
32
33 // Sorts the values of the ArrayList using the default comparer.
34 myAL.Sort();
35 Console.WriteLine( "After sorting with the default comparer:" );
36 PrintIndexAndValues( myAL );
37
38 // Sorts the values of the ArrayList using the reverse case-insensitive comparer.
39 IComparer myComparer = new myReverserClass();
40 myAL.Sort( myComparer );
41 Console.WriteLine( "After sorting with the reverse case-insensitive comparer:" );
42 PrintIndexAndValues( myAL );
43
44 }
45
46 public static void PrintIndexAndValues( IEnumerable myList ) {
47 int i = 0;
48 foreach ( Object obj in myList )
49 Console.WriteLine( "\t[{0}]:\t{1}", i++, obj );
50 Console.WriteLine();
51 }
52
53}
54
55
56/**//*
57This code produces the following output.
58The ArrayList initially contains the following values:
59 [0]: The
60 [1]: quick
61 [2]: brown
62 [3]: fox
63 [4]: jumps
64 [5]: over
65 [6]: the
66 [7]: lazy
67 [8]: dog
68
69After sorting with the default comparer:
70 [0]: brown
71 [1]: dog
72 [2]: fox
73 [3]: jumps
74 [4]: lazy
75 [5]: over
76 [6]: quick
77 [7]: the
78 [8]: The
79
80After sorting with the reverse case-insensitive comparer:
81 [0]: the
82 [1]: The
83 [2]: quick
84 [3]: over
85 [4]: lazy
86 [5]: jumps
87 [6]: fox
88 [7]: dog
89 [8]: brown
90*/