设计模式系列漫谈之十二 - 职责链模式
从牙膏广告说起
在午茶小憩间,以“成语接龙”形式,通过帅哥美女之口巧妙地把牙齿常见的症状表达出来,从而突出云南白药牙膏的独特功效。这一极其创意的广告为云南白药赢得了巨大的市场,也使其产品为广大消费者所熟悉,创造了家喻户晓的品牌效应。
成语接龙是一种人们喜闻乐见的游戏。就游戏规则来讲非常简单,即用前一个成语的尾字作为下一个成语的首字。我们可以认为,游戏参与者需要做三件事情:一是接前一位参与人的成语首字;二是说出成语;三是把成语尾字传给后一位参与人。
职责链(Chain of Responsibility)模式
在对很多对象进行处理时,由每一个对象对其下一对象的引用,从而连接起一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。职责链可以是一条线,一个树,也可以是一个环。职责链模式需要定义两个角色:
抽象处理者角色:定义出一个处理请求的接口。并且定义一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。
具体处理者角色:具体处理者接到请求后,可以处理请求,并将请求传给下一对象。
下面通过程序来实现如下游戏:
白领一:生龙活虎 白领二:虎口拔牙 白领三:牙龈肿痛 白领四:痛不欲生
抽象处理者(AbstractMember)角色如下:
public class AbstractMember
{
protected AbstractMember _member;
public void SetMember(AbstractMember member)
{
this._member = member;
}
public abstract void Say(string begin);
}
{
protected AbstractMember _member;
public void SetMember(AbstractMember member)
{
this._member = member;
}
public abstract void Say(string begin);
}
具体处理者(Member)角色如下:
public class Member:AbstractMember
{
private string _first;
private string _cy;
public Member(string first,string cy)
{
this._first=first;
this._cy=cy;
}
public override void Say(string nextbegin)
{
Console.WriteLine(this._cy);
if (this._cy.StartsWith(this._first))
{
Console.WriteLine("游戏结束");
}
if (!this._cy.StartsWith(nextbegin))
{
Console.WriteLine("违反规则了");
}
if (_member!=null)
{
nextbegin=this._cy.SubString(0,1); //获取首字
_member.Say(nextbegin); //传下一位
}
}
}
{
private string _first;
private string _cy;
public Member(string first,string cy)
{
this._first=first;
this._cy=cy;
}
public override void Say(string nextbegin)
{
Console.WriteLine(this._cy);
if (this._cy.StartsWith(this._first))
{
Console.WriteLine("游戏结束");
}
if (!this._cy.StartsWith(nextbegin))
{
Console.WriteLine("违反规则了");
}
if (_member!=null)
{
nextbegin=this._cy.SubString(0,1); //获取首字
_member.Say(nextbegin); //传下一位
}
}
}
客户端调用如下:
public class Client
{
public static void Main()
{
Member m1=new Member("生","生龙活虎");
Member m2=new Member("生","虎口拔牙");
Member m3=new Member("生","牙龈肿痛");
Member m4=new Member("生","痛不欲生");
m1.SetMember(m2);
m2.SetMember(m3);
m3.SetMember(m4);
m4.SetMember(m1);
m1.Say("虎");
}
}
{
public static void Main()
{
Member m1=new Member("生","生龙活虎");
Member m2=new Member("生","虎口拔牙");
Member m3=new Member("生","牙龈肿痛");
Member m4=new Member("生","痛不欲生");
m1.SetMember(m2);
m2.SetMember(m3);
m3.SetMember(m4);
m4.SetMember(m1);
m1.Say("虎");
}
}