行为模式(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)角色: 定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。
具体处理者(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 ); } }
六、 责任链模式的实现 责任链模式并不创建责任链。责任链的创建必须由系统的其它部分创建出来。
责任链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。一个链可以是一条线,一个树,也可以是一个环。如下图所示,责任链是一个树结构的一部分。
参考文献: 阎宏,《Java与模式》,电子工业出版社 [美]James W. Cooper,《C#设计模式》,电子工业出版社 [美]Alan Shalloway James R. Trott,《Design Patterns Explained》,中国电力出版社 [美]Robert C. Martin,《敏捷软件开发-原则、模式与实践》,清华大学出版社 [美]Don Box, Chris Sells,《.NET本质论 第1卷:公共语言运行库》,中国电力出版社
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人