行為模式(Behavioral Pattern)是對在不同的對象之間劃分責任和算法的抽象化。行為模式不僅僅是關於類和對象的,而且是關於它們之間的相互作用的。
行為模式分為類的行為模式和對象的行為模式兩種。
類的行為模式:類的行為模式使用繼承關系在幾個類之問分配行為。
對象的行為模式:對象的行為模式則使用對象的聚合來分配行為。
在後面將要介紹的行為模式包括以下幾種:
Chain of Resp.(責任鏈模式)A way of passing a request between a chain of objects
Command(命令模式)Encapsulate a command request as an object
Interpreter(解釋器模式)A way to include language elements in a program
Iterator(迭代子模式)Sequentially access the elements of a collection
Mediator(中介者模式)Defines simplified communication between classes
Memento(備忘錄模式)Capture and restore an object's internal state
Observer(觀察者模式)A way of notifying change to a number of classes
State(狀態模式)Alter an object's behavior when its state changes
Strategy(策略模式)Encapsulates an algorithm inside a class
Template Method(模版方法模式)Defer the exact steps of an algorithm to a subclass
Visitor(訪問者模式)Defines a new operation to a class without change
一、職責鏈(Chain of Responsibility)模式
責任鏈模式是一種對象的行為模式【GOF95】。在責任鏈模式裡,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。
從擊鼓傳花談起
擊鼓傳花是一種熱鬧而又緊張的飲酒游戲。在酒宴上賓客依次坐定位置,由一人擊鼓,擊鼓的地方與傳花的地方是分開的,以示公正。開始擊鼓時,花束就開始依次傳遞,鼓聲一落,如果花束在某人手中,則該人就得飲酒。
擊鼓傳花便是責任鏈模式的應用。責任鏈可能是一條直線、一個環鏈或者一個樹結構的一部分。
二、責任鏈模式的結構
責任鏈模式涉及到的角色如下所示:
抽象處理者(Handler)角色:定義出一個處理請求的接口。如果需要,接口可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類或接口實現。---www.bianceng.cn
具體處理者(ConcreteHandler)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
三、責任鏈模式的示意性源代碼
// Chain of Responsibility pattern -- Structural example
using System;
// "Handler"
abstract class Handler
{
// Fields
protected Handler successor;
// Methods
public void SetSuccessor( Handler successor )
{
this.successor = successor;
}
abstract public void HandleRequest( int request );
}
// "ConcreteHandler1"
class ConcreteHandler1 : Handler
{
// Methods
override public void HandleRequest( int request )
{
if( request >= 0 && request < 10 )
Console.WriteLine("{0} handled request {1}",
this, request );
else
if( successor != null )
successor.HandleRequest( request );
}
}
// "ConcreteHandler2"
class ConcreteHandler2 : Handler
{
// Methods
override public void HandleRequest( int request )
{
if( request >= 10 && request < 20 )
Console.WriteLine("{0} handled request {1}",
this, request );
else
if( successor != null )
successor.HandleRequest( request );
}
}
// "ConcreteHandler3"
class ConcreteHandler3 : Handler
{
// Methods
override public void HandleRequest( int request )
{
if( request >= 20 && request < 30 )
Console.WriteLine("{0} handled request {1}",
this, request );
else
if( successor != null )
successor.HandleRequest( request );
}
}
/**//// <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
// Generate and process request
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach( int request in requests )
h1.HandleRequest( request );
}
}
四、純的與不純的責任鏈模式
一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行為中選擇一個:一個是承擔責任,二是把責任推給下家。不允許出現某一個具體處理者對象在承擔了一部分責任後又把責任向下傳的情況。
在一個純的責任鏈模式裡面,一個請求必須被某一個處理者對象所接收;在一個不純的責任鏈模式裡面,一個請求可以最終不被任何接收端對象所接收。純的責任鏈模式的例子是不容易找到的,一般看到的例子均是不純的責任鏈模式的實現。
五、責任鏈模式的實際應用案例
下面的責任鏈模式代碼演示了不同職務的人根據所設定的權限對一個購買請求作出決策或將其交給更高的決策者。
// Chain of Responsibility pattern -- Real World example
using System;
// "Handler"
abstract class Approver
{
// Fields
protected string name;
protected Approver successor;
// Constructors
public Approver( string name )
{
this.name = name;
}
// Methods
public void SetSuccessor( Approver successor )
{
this.successor = successor;
}
abstract public void ProcessRequest( PurchaseRequest request );
}
// "ConcreteHandler"
class Director : Approver
{
// Constructors
public Director ( string name ) : base( name ) {}
// Methods
override public void ProcessRequest( PurchaseRequest request )
{
if( request.Amount < 10000.0 )
Console.WriteLine( "{0} {1} approved request# {2}",
this, name, request.Number);
else
if( successor != null )
successor.ProcessRequest( request );
}
}
// "ConcreteHandler"
class VicePresident : Approver
{
// Constructors
public VicePresident ( string name ) : base( name ) {}
// Methods
override public void ProcessRequest( PurchaseRequest request )
{
if( request.Amount < 25000.0 )
Console.WriteLine( "{0} {1} approved request# {2}",
this, name, request.Number);
else
if( successor != null )
successor.ProcessRequest( request );
}
}
// "ConcreteHandler"
class President : Approver
{
// Constructors
public President ( string name ) : base( name ) {}
// Methods
override public void ProcessRequest( PurchaseRequest request )
{
if( request.Amount < 100000.0 )
Console.WriteLine( "{0} {1} approved request# {2}",
this, name, request.Number);
else
Console.WriteLine( "Request# {0} requires " +
"an executive meeting!", request.Number );
}
}
// Request details
class PurchaseRequest
{
// Member Fields
private int number;
private double amount;
private string purpose;
// Constructors
public PurchaseRequest( int number,
double amount, string purpose )
{
this.number = number;
this.amount = amount;
this.purpose = purpose;
}
// Properties
public double Amount
{
get{ return amount; }
set{ amount = value; }
}
public string Purpose
{
get{ return purpose; }
set{ purpose = value; }
}
public int Number
{
get{ return number; }
set{ number = value; }
}
}
/**//// <summary>
/// ChainApp Application
/// </summary>
public class ChainApp
{
public static void Main( string[] args )
{
// Setup Chain of Responsibility
Director Larry = new Director( "Larry" );
VicePresident Sam = new VicePresident( "Sam" );
President Tammy = new President( "Tammy" );
Larry.SetSuccessor( Sam );
Sam.SetSuccessor( Tammy );
// Generate and process different requests
PurchaseRequest rs = new PurchaseRequest( 2034, 350.00, "Supplies" );
Larry.ProcessRequest( rs );
PurchaseRequest rx = new PurchaseRequest( 2035, 32590.10, "Project X" );
Larry.ProcessRequest( rx );
PurchaseRequest ry = new PurchaseRequest( 2036, 122100.00, "Project Y" );
Larry.ProcessRequest( ry );
}
}
六、責任鏈模式的實現
責任鏈模式並不創建責任鏈。責任鏈的創建必須由系統的其它部分創建出來。
責任鏈模式降低了請求的發送端和接收端之間的耦合,使多個對象都有機會處理這個請求。一個鏈可以是一條線,一個樹,也可以是一個環。如下圖所示,責任鏈是一個樹結構的一部分。