java责任链模式模拟拱猪入门打一字游戏一轮出牌的过程

9531人阅读
设计模式(20)
本文继续介绍之职责链模式。什么是链1、链是一系列节点的集合。2.、链的各节点可灵活拆分再重组。职责链模式使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。角色抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。抽象处理者角色public abstract class Handler {
* 持有后继的责任对象
protected H
* 示意处理请求的方法,虽然这个示意方法是没有传入参数的
* 但实际是可以传入参数的,根据具体需要来选择是否传递参数
public abstract void handleRequest();
* 取值方法
public Handler getSuccessor() {
* 赋值方法,设置后继的责任对象
public void setSuccessor(Handler successor) {
this.successor =
}具体处理者角色public class ConcreteHandler extends Handler {
* 处理方法,调用此方法处理请求
public void handleRequest() {
* 判断是否有后继的责任对象
* 如果有,就转发请求给后继的责任对象
* 如果没有,则处理请求
if(getSuccessor() != null)
System.out.println(&放过请求&);
getSuccessor().handleRequest();
System.out.println(&处理请求&);
}客户端类public class Client {
public static void main(String[] args) {
//组装责任链
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
//提交请求
handler1.handleRequest();
}可以看出,客户端创建了两个处理者对象,并指定第一个处理者对象的下家是第二个处理者对象,而第二个处理者对象没有下家。然后客户端将请求传递给第一个处理者对象。由于本示例的传递逻辑非常简单:只要有下家,就传给下家处理;如果没有下家,就自行处理。因此,第一个处理者对象接到请求后,会将请求传递给第二个处理者对象。由于第二个处理者对象没有下家,于是自行处理请求。活动时序图如下所示。应用申请聚餐费用的管理,申请聚餐费用的大致流程一般是,由申请人先填写申请单,然后交给领导审批,如果申请批准下来,领导会通知申请人审批通过,然后申请人去财务领取费用,如果没有批准下来,领导会通知申请人审批未通过,此事也就此作罢。不同级别的领导,对于审批的额度是不一样的,比如,项目经理只能审批500元以内的申请;部门经理能审批1000元以内的申请;而总经理可以审核任意额度的申请。当某人提出聚餐费用申请的请求后,该请求会经由项目经理、部门经理、总经理之中的某一位领导来进行相应的处理,但是提出申请的人并不知道最终会由谁来处理他的请求,一般申请人是把自己的申请提交给项目经理,或许最后是由总经理来处理他的请求。申请人只要直接与项目经理交互就可以,其余的工作在黑盒中,究竟流程是怎样的,最后是由谁审批通过的,申请人无需关心。抽象处理者角色类public abstract class Handler {
* 持有下一个处理请求的对象
protected Handler successor =
* 取值方法
public Handler getSuccessor() {
* 设置下一个处理请求的对象
public void setSuccessor(Handler successor) {
this.successor =
* 处理聚餐费用的申请
* @param user
* @param fee
申请的钱数
成功或失败的具体通知
public abstract String handleFeeRequest(String user , double fee);
}具体处理者角色public class ProjectManager extends Handler {
public String handleFeeRequest(String user, double fee) {
String str = &&;
//项目经理权限比较小,只能在500以内
if(fee & 500)
//为了测试,简单点,只同意张三的请求
if(&张三&.equals(user))
str = &成功:项目经理同意【& + user + &】的聚餐费用,金额为& + fee + &元&;
//其他人一律不同意
str = &失败:项目经理不同意【& + user + &】的聚餐费用,金额为& + fee + &元&;
//超过500,继续传递给级别更高的人处理
if(getSuccessor() != null)
return getSuccessor().handleFeeRequest(user, fee);
}public class DeptManager extends Handler {
public String handleFeeRequest(String user, double fee) {
String str = &&;
//部门经理的权限只能在1000以内
if(fee & 1000)
//为了测试,简单点,只同意张三的请求
if(&张三&.equals(user))
str = &成功:部门经理同意【& + user + &】的聚餐费用,金额为& + fee + &元&;
//其他人一律不同意
str = &失败:部门经理不同意【& + user + &】的聚餐费用,金额为& + fee + &元&;
//超过1000,继续传递给级别更高的人处理
if(getSuccessor() != null)
return getSuccessor().handleFeeRequest(user, fee);
}public class GeneralManager extends Handler {
public String handleFeeRequest(String user, double fee) {
String str = &&;
//总经理的权限很大,只要请求到了这里,他都可以处理
if(fee &= 1000)
//为了测试,简单点,只同意张三的请求
if(&张三&.equals(user))
str = &成功:总经理同意【& + user + &】的聚餐费用,金额为& + fee + &元&;
//其他人一律不同意
str = &失败:总经理不同意【& + user + &】的聚餐费用,金额为& + fee + &元&;
//如果还有后继的处理对象,继续传递
if(getSuccessor() != null)
return getSuccessor().handleFeeRequest(user, fee);
}客户端类public class Client {
public static void main(String[] args) {
//先要组装责任链
Handler h1 = new GeneralManager();
Handler h2 = new DeptManager();
Handler h3 = new ProjectManager();
h3.setSuccessor(h2);
h2.setSuccessor(h1);
//开始测试
String test1 = h3.handleFeeRequest(&张三&, 300);
System.out.println(&test1 = & + test1);
String test2 = h3.handleFeeRequest(&李四&, 300);
System.out.println(&test2 = & + test2);
System.out.println(&---------------------------------------&);
String test3 = h3.handleFeeRequest(&张三&, 700);
System.out.println(&test3 = & + test3);
String test4 = h3.handleFeeRequest(&李四&, 700);
System.out.println(&test4 = & + test4);
System.out.println(&---------------------------------------&);
String test5 = h3.handleFeeRequest(&张三&, 1500);
System.out.println(&test5 = & + test5);
String test6 = h3.handleFeeRequest(&李四&, 1500);
System.out.println(&test6 = & + test6);
}职责链灵活在哪1. 改变内部的传递规则在内部,项目经理完全可以跳过人事部到那一关直接找到总经理。每个人都可以去动态地指定他的继任者。2. 可以从职责链任何一关开始。如果项目经理不在,可以直接去找部门经理,责任链还会继续,没有影响。3.用与不用的区别不用职责链的结构,我们需要和公司中的每一个层级都发生耦合关系。如果反映在代码上即使我们需要在一个类中去写上很多丑陋的if….else语句。如果用了职责链,相当于我们面对的是一个黑箱,我们只需要认识其中的一个部门,然后让黑箱内部去负责传递就好了纯的与不纯的责任链模式一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。更多设计模式:作者:jason0539博客:(转载请说明出处)推荐扫码关注微信公众号,给生活添点色彩
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2703816次
积分:17438
积分:17438
排名:第432名
原创:183篇
转载:12篇
评论:774条
====原创====
====思考====
你花六块八块买个盒饭吃,觉得很节省,有人在路边买了七毛钱馒头吞咽后步履匆匆;
你八点起床看书,觉得很勤奋,上微博发现曾经的同学八点就已经在面对繁重的工作;
你周六补个课,觉得很累,打个电话才知道许多朋友都连续加班了一个月。
亲爱的,你真的还不够苦,不够勤奋和努力。
(1)(1)(1)(1)(1)(7)(18)(4)(1)(1)(2)(2)(3)(13)(14)(6)(5)(9)(12)(55)(22)(7)(2)(1)(2)(3)
====思想====
====内容====17yy拱猪游戏单机版
滑动星星评分
同类游戏推荐
游戏评分:
分类:|大小:322.34 KB||日期:|
拱猪游戏单机版,一款非常好玩的扑克牌游戏。拱猪游戏,需要玩家出掉手中的牌、避免得分,并争取在游戏结束时得分最低。拱猪游戏由四个玩家一同进行,使用一副去掉大、小王的扑克牌,只要任何一个玩家的得分超过100分,游戏即结束。
拱猪游戏又名红心大战,分值有黑桃Q,红心。每人有13张牌,选出三张牌传给其他对手。传牌的顺序是第一局传左家,第二局右家,第三局对家,第四局不传牌。抓有梅花 2 的玩家首先出梅花 2。然后按顺时针方向出牌。每位玩家依次必须跟同花色牌。如果已经没有与发牌花色相同的牌,则可以出任意一张牌。
拱猪游戏怎么玩(游戏规则):
&交换后手中有草花2的人作为庄家。庄家先出。
&每局游戏的第一轮必须出草花2;
&若本局游戏还没有出过红桃且手中还有除红桃外的其他牌时不能出红桃;
&其他玩家出牌时,先出和庄家牌花色一致的牌,若没有该花色的牌可任选一张出掉。
&每局游戏的第一轮不能出分值牌(黑桃Q和红桃)。
&四个玩家都出了牌后,根据大小判断规则找出出牌最大的玩家,作为下一轮的庄家,同时把本轮牌中的所有分值牌的分数总和加到该玩家的积分上。
&所有的牌都出完后一局游戏结束。当某一玩家在一局中得了26分(拿了黑桃Q和13张红桃)称为&全红&,这是需要奖励的:本局得分为零,其他三个玩家各得26分。
更详细介绍请查看本站文章:
如果你喜欢本游戏,请把17yy告诉你的好朋友,让他和你一起分享快乐! 我们的网址是:
评论加载中......
棋牌游戏排行榜java责任链
初看责任链模式,心里不禁想起了一个以前听过的相声:看牙。说的是一个病人看牙的时候,医生不小心把拔下的一个牙掉进了病人嗓子里。病人因此楼上楼下的跑了好多科室,最后无果而终。
责任链模式就是这种“推卸”责任的模式,你的问题在我这里能解决我就解决,不行就把你推给另一个对象。至于到底谁解决了这个问题了呢?我管呢!
二、定义与结构
从名字上大概也能猜出这个模式的大概模样——系统中将会存在多个有类似处理能力的对象。当一个请求触发后,请求将在这些对象组成的链条中传递,直到找到最合适的“责任”对象,并进行处理。
《设计模式》中给它的定义如下:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
从定义上可以看出,责任链模式的提出是为了“解耦”,以应变系统需求的变更和不明确性。
下面是《设计模式》中给出的适用范围:
有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3) 可处理一个请求的对象集合应被动态指定。
责任链模式真的能给发送者和接收者之间解耦(这好像很神奇)吗?先来看下它的组成角色。这个问题我会在下面提及。
责任链模式由两个角色组成:
抽象处理者角色(Handler):它定义了一个处理请求的接口。当然对于链子的不同实现,也可以在这个角色中实现后继链。
2) 具体处理者角色(Concrete
Handler):实现抽象角色中定义的接口,并处理它所负责的请求。如果不能处理则访问它的后继者。
至于类图不放也罢。毕竟就是一个继承或者实现。
三、纯与不纯
责任链模式的纯与不纯的区别,就像黑猫、白猫的区别一样。不要刻意的去使自己的代码来符合一个模式的公式。只要能够使代码降低耦合、提高重用,满足系统需求并能很好的适应变化就好了。正所谓:管它黑猫白猫,抓住老鼠就是好猫!
纯的责任链模式,规定一个具体处理者角色只能对请求作出两种动作:自己处理;传给下家。不能出现处理了一部分,把剩下的传给了下家的情况。而且请求在责任链中必须被处理,而不能出现无果而终的结局。
反之,则就是不纯的责任链模式。
不纯的责任链模式还算是责任链模式吗?比如一个请求被捕获后,每个具体处理者都尝试去处理它,不管结果如何都将请求再次转发。我认为这种方式的实
现,算不算是责任链模式的一种倒不重要,重要的是我们也能从中体味到责任链模式的思想:通过将多个处理者之间建立联系,来达到请求与具体的某个处理者的解
举例:这个列子真他妈的简单易懂,我都已看就明白,
public interface Chain {
&&& public
abstract void addChain(Chain c);
&&& public
abstract void sendToChain(String mesg);
&&& public
abstract Chain getChain();
public class Manager implements
&&& private
Chain nextChain =
&&& private
String responsibility = "Get Project";;
&&& public
Manager() {
&&& public void
addChain(Chain c) {
nextChain =
&&& public Chain
getChain() {
return nextC
&&& public void
sendToChain(String mesg) {
if(mesg.equals(responsibility)) {
&&&&&&&&&&&
System.out.println("A manager --& Get a
Project");
&&&&&&&&&&&
if(nextChain != null) {
&&&&&&&&&&&&&&&
nextChain.sendToChain(mesg);
&&&&&&&&&&&
public class ProjectManager
implements Chain {
&&& private
Chain nextChain =
&&& private
String responsibility = "Design";
&&& public
ProjectManager() {
&&& public void
addChain(Chain c) {
nextChain =
&&& public Chain
getChain() {
return nextC
&&& public void
sendToChain(String mesg) {
if(mesg.equals(responsibility)) {
&&&&&&&&&&&
System.out.println("A PM --& Design");
&&&&&&&&&&&
if(nextChain != null) {
&&&&&&&&&&&&&&&
nextChain.sendToChain(mesg);
&&&&&&&&&&&
public class Others implements Chain {
&&& private
Chain nextChain =
&&& private
String responsibility = "";
&&& public
Others() {
&&& public void
addChain(Chain c) {
nextChain =
&&& public Chain
getChain() {
return nextC
&&& public void
sendToChain(String mesg) {
&&&&&&&&&&&
System.out.println("No one can handle --& " +
public class Test {
&&& public
static void main(String[] args) {
Manager aManager = new Manager();
ProjectManager aPM = new ProjectManager();
Others others = new Others();
aManager.addChain(aPM);
aPM.addChain(others);
aManager.sendToChain("Get Project");
aManager.sendToChain("Design");
aManager.sendToChain("Coding");
aManager.sendToChain("Test");
aManager.sendToChain("Kill La Deng !");
把自己能解决的自己解决掉,自己不能解决的交给其它去解决,就这样一个传一个,不管最终谁解决了这个问题,降低耦合,
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。详解java设计模式之责任链模式 - grefr - 博客园
随笔 - 278, 文章 - 0, 评论 - 2, 引用 - 0
从击鼓传花谈起  击鼓传花是一种热闹而又紧张的饮酒游戏。在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传花的地方是分开的,以示公正。开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在某人手中,则该人就得饮酒。  假比说,贾母、贾赦、贾政、贾宝玉和贾环是五个参加击鼓传花游戏的传花者,他们组成一个环链。击鼓者将花传给贾母,开始传花游戏。花由贾母传给贾赦,由贾赦传给贾政,由贾政传给贾宝玉,又由贾宝玉传给贾环,由贾环传回给贾母,如此往复(见下图)。当鼓声停止时,手中有花的人就得执行酒令。
图1、击鼓传花。  击鼓传花便是责任链模式的应用。在责任链模式里,很多的对象由每一个对象对其下家的引用而联接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。  责任链可能是一条直线、一个环链甚至一个树结构的一部分。  责任链模式的结构  责任链模式是一种对象的行为模式,它所涉及到的角色如下:  第一、抽象处理者(Handler)角色、定义出一个处理请求的接口;如果需要,接口可以定义出一个方法,以返回对下家的引用。下图给出了一个示意性的类图:图2、抽象处理者角色。&  在图中的积累关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。  第二、具体处理者(ConcreteHandler)角色、处理接到请求后,可以选择将请求处理掉,或者将请 求传给下家。下图给出了一个示意性的类图。&图3、具体处理者角色。&  上图中的示意性的具体处理者ConcreteHandler类只有handleRequest()一个方法。  责任链模式的静态类结构可见下图:  图4、责任链模式的类图定义。  在图中还给出了一个客户端,以便读者可以更清楚地看到责任链模式是怎样应用的。抽象处理者的示意性源代码:
public class Handler {  public void handleRequest()&   {    if (successor != null)&     {&       successor.handleRequest();      }&     // Write your code here    }  public void setSuccessor(Handler successor)&    {&     this.successor =&    }  public Handler getSuccessor()&   {&      }  private H&  }
  代码清单1、抽象处理者的源代码。  具体处理者的示意性源代码:&
public class ConcreteHandler extends Handler  {&   public void handleRequest()&    {&     if (getSuccessor() != null)&     {      getSuccessor().handleRequest();&     }&     if (successor != null)     {&      successor.handleRequest();     }    // Write your code here&    }  }
  代码清单2、具体处理者的源代码。&  客户端的源代码如下:
public class Client&  {   private H&   public static void main(String[] args)    {     handler = new ConcreteHandler();     //write your code here    }  }
  代码清单3、客户端的源代码
纯的与不纯的责任链模式  一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,二是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又把责任向下传的情况。  在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接受;在一个不纯的责任链模式里面,一个请求可以最终不被任何接受端对象所接受。  纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的;但是在实际的系统里,纯的责任链很难找到;如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大的意义了。  Java1.0版的AWT事件处理机制  Java的1.0版中AWT库使用了责任链模式和命令模式来处理GUI的事件。由于视窗部件往往处在容器部件里面,因此当事件发生在一个部件上时,此部件的事件处理器可以处理此事件,然后决定是否将事件向上级容器部件传播;上级容器部件接到事件后可以在此处理此事件然后决定是否将事件再次向上级容器部件传播,如此往复,直到事件到达顶层部件。
  事件浮升机制
  比如,当一个视窗部件接到一个MOUSE_CLICKED事件时,事件首先传播到它所发生的部件上,然后向其容器部件传播。容器可以选择处理这个事件,或者再将此事件向更高一级的容器部件传播。事件如此一级级地向上传播,就像水底的气泡一点一点地冒到水面上一样,因此又叫做事件浮升(Event Bubbling)机制。下面就是一段典型的Java1.0版的AWT库里处理事件的代码:
public boolean action(Event event, Object obj)&  {&    if (event.target == btnOK)     {&      doOKBtnAction();     }    else if (event.target == btnExit)&     {&      doExitBtnAction();&     }&    else&     {      return super.action(event, obj);     }     }
代码清单4、Java1.0版本中AWT处理事件的典型代码。&  在这段代码里面,action()判断目标部件是不是btnOK或btnExit;如果是,便运行相应的方法;如果不是,便返还true。一个方法返还true便使得事件停止浮升。
  AWT1.0的事件处理的模型的缺点之一
  AWT1.0的事件处理的模型是基于继承的。为了使一个程序能够捕捉GUI的事件并处理此事件,必须subclass此部件并且给其子类配备事件处理器,也就是置换掉action()方法或者handleEvent()方法。这不是应当提倡的做法:在一个面向对象的系统里,经常使用的应当是委派,继承不应当是常态。  在一个复杂的GUI系统里,这样为所有有事件的部件提供子类,会导致很多的子类,这是不是很麻烦的吗?  当然,由于事件浮升机制,可以在部件的树结构的根部部件里面处理所有的事件。但是这样一来,就需要使用复杂的条件转移语句在这个根部部件里辨别事件的起源和处理方法。这种非常过程化的处理方法很难维护,并且与面向对象的设计思想相违背。
  AWT1.0的事件处理的模型的缺点之二
  由于每一个事件都会沿着部件树结构向上传播,因此事件浮升机制会使得事件的处理变得较慢。这也是缺点之一。  比如在有些操作系统中,鼠标每移动一个色素,都会激发一个MOUSE_MOVE事件。每一个这样的事件都会沿着部件的容器树结构向上传播,这会使得鼠标事件成灾。
  AWT1.0的事件处理的模型的缺点之三
  AWT1.0的事件处理的模型只适用于AWT部件类。这是此模型的另一个缺点。  责任链模式要求链上所有的对象都继承自一个共同的父类,这个类便是ponent类。
  AWT1.0的事件处理的模型是不纯的责任链模式
  显然,由于每一级的部件在接到事件时,都可以处理此事件;而不论此事件是否在这一级得到处理,事件都可以停止向上传播或者继续向上传播。这是典型的不纯的责任链模式。
  AWT1.1以后的事件处理的模型
  自从AWT1.1以后,AWT的事件处理模型于1.0相比有了很大的变化。新的事件处理模型是建立在观察者模式的基础之上的,而不再是责任链模式的基础之上的。  关于新的事件处理模型和观察者设计模式,请见“观察者模式”一节.
红楼梦中击鼓传花的故事  显然,击鼓传花符合责任链模式的定义。参加游戏的人是一个个的具体处理者对象,击鼓的人便是客户端对象。花代表酒令,是传向处理者的请求,每一个参加游戏的人在接到传来的花时,可选择的行为只有两个:一是将花向下传;一是执行酒令---喝酒。一个人不能既执行酒令,又向下家传花;当某一个人执行了酒令之后,游戏重新开始。击鼓的人并不知道最终是由哪一个做游戏的人执行酒令,当然执行酒令的人必然是做游戏的人们中的一个。  击鼓传花的类图结构如下:图5、击鼓传花系统的类图定义。  单独考虑击鼓传花系统,那么像贾母、贾赦、贾政、贾宝玉和贾环等传花者均应当是“具体传花者”的对象,而不应当是单独的类;但是责任链模式往往是建立在现有系统的基础之上的,因此链的结构和组成不由责任链模式本身决定。
  系统的分析
  在《红楼梦》第七十五回里生动地描述了贾府里的一场击鼓传花游戏:“贾母坐下,左垂首贾赦,贾珍,贾琏,贾蓉,右垂首贾政,宝玉,贾环,贾兰,团团围坐。...贾母便命折一枝桂花来,命一媳妇在屏后击鼓传花。若花到谁手中,饮酒一杯...于是先从贾母起,次贾赦,一一接过。鼓声两转,恰恰在贾政手中住了,只得饮了酒。”这场游戏接着又把花传到了宝玉和贾赦手里,接着又传到了在贾环手里...
  如果用一个对象系统描述贾府,那么贾母、贾赦、贾政、贾宝玉和贾环等等就应当分别由一个个具体类代表,而这场击鼓传花游戏的类图,按照责任链模式,应当如下图所示:图6、红楼梦中的击鼓传花游戏的示意性类图。&  换言之,在击鼓传花游戏里面,有下面的几种角色:
 抽象传花者,或Handler角色、定义出参加游戏的传花人要遵守的规则,也就是一个处理请求的接口 和对下家的引用;
 具体传花者,或ConcreteHandler角色、每一个传花者都知道下家是谁,要么执行酒令,要么把花 向下传。这个角色由贾母、贾赦、贾珍、贾琏、贾蓉、贾政、宝玉、贾环、贾兰等扮演。
 击鼓人,或Client角色、即行酒令的击鼓之人。《红楼梦》没有给出此人的具体姓名,只是说由“一 媳妇”扮演。
图7、贾府这次击鼓传花的示意性对象图。&  可以看出,击鼓传花游戏满足责任链模式的定义,是纯的责任链模式的例子.
Java系统的解  下面的类图给出了这些类的具体接口设计。读者不难看出,DrumBeater(击鼓者)、Player(传花者)、JiaMu(贾母)、JiaShe(贾赦)、JiaZheng(贾政)、JiaBaoYu(宝玉)、JiaHuan(贾环)等组成这个系统。图8、击鼓传花的类图完全符合责任链模式的定义。&  下面是客户端类DrumBeater的源代码:
public class DrumBeater&{  private static P  static public void main(String[] args)&   {&    player = new JiaMu( new JiaShe( new JiaZheng( new JiaBaoYu(new JiaHuan(null)))));&    player.handle(4);   }&}
  代码清单5、DrumBeater的源代码。&
abstract class Player&{  abstract public void handle(int i);  private P&  public Player() { successor =}protected void setSuccessor(Player aSuccessor)&{  successor = aS}public void next(int index){&  if( successor != null )&   {&    successor.handle(index);   }  else&   {&    System.out.println("Program terminated.");&   }  }}
  代码清单6、抽象传花者Play类的源代码。&  抽象类Player给出了两个方法的实现,以格式setSuccessor(),另一个是next()。前者用来设置一个传花者对象的下家,后者用来将酒令传给下家。Player类给出了一个抽象方法handle(),代表执行酒令。  下面的这些具体传花者类将给出handle()方法的实现。
class JiaMu extends Player&  {   public JiaMu(Player aSuccessor)   {&    this.setSuccessor(aSuccessor);   }   public void handle(int i)   {&    if( i == 1 )    {&     System.out.println("Jia Mu gotta drink!");&    }    else    {&     System.out.println("Jia Mu passed!"); next(i);    }   }  }
  代码清单7、代表贾母的JiaMu类的源代码。&
class JiaShe extends Player&  {   public JiaShe(Player aSuccessor)   {    this.setSuccessor(aSuccessor);&   }   public void handle(int i)    {&     if( i == 2 )&     {      System.out.println("Jia She gotta drink!");&     }     else     {      System.out.println("Jia She passed!");      next(i);     }    }  }
  代码清单8、代表贾赦的JiaShe类的源代码。&
class JiaZheng extends Player&  {   public JiaZheng(Player aSuccessor)   {    this.setSuccessor(aSuccessor);&   }   public void handle(int i)   {&    if( i == 3 )    {&     System.out.println("Jia Zheng gotta drink!");    }&    else    {     System.out.println("Jia Zheng passed!");&     next(i);&    }   }  }
  代码清单9、代表贾政的JiaZheng类的源代码。&
class JiaBaoYu extends Player  {   public JiaBaoYu(Player aSuccessor)   {    this.setSuccessor(aSuccessor);&   }   public void handle(int i)   {    if( i == 4 )&    {     System.out.println("Jia Bao Yu gotta drink!");    }&    else    {     System.out.println("Jia Bao Yu passed!");     next(i);    }   }  }
  代码清单10、代表贾宝玉的JiaBaoYu类的源代码。&
class JiaHuan extends Player&  {   public JiaHuan(Player aSuccessor)&    {&     this.setSuccessor(aSuccessor);    }   public void handle(int i)   {    if( i == 5 )    {     System.out.println("Jia Huan gotta drink!");    }    else    {     System.out.println("Jia Huan passed!");     next(i);    }   }  }
  代码清单11、代表贾环的JiaHuan类的源代码。&  可以看出,DrumBeater设定了责任链的成员和他们的顺序:责任链由贾母开始到贾环,周而复始。JiaMu类、JiaShe类、JiaZheng类、JiaBaoYu类与JiaHuan类均是抽象传花者Player类的子类。  本节所实现的DrumBeater类在把请求传给贾母时,实际上指定了由4号传花者处理酒令。虽然DrumBeater并不知道哪一个传花者类持有号码4,但是这个号码在本系统一开始就写死的。这当然并不符合击鼓传花游戏的精神,因为这个游戏实际上要求有两个同时进行的过程:击鼓过程和传花过程。击鼓应当是定时停止的,当击鼓停止时,执行酒令者就确定了。但是本节这样做可以使问题得到简化并将读者的精力放在责任链模式上,而不是两个过程的处理上。  下一章会给出一个多线程的系统,更加逼真地模拟击鼓传花系统。
在什么情况下使用责任链模式  在下面的情况下使用责任链模式:  第一、系统已经有一个由处理者对象组成的链。这个链可能由复合模式给出,  第一、当有多于一个的处理者对象会处理一个请求,而且在事先并不知道到底由哪一个处理者对象处理一个请求。这个处理者对象是动态确定的。  第二、当系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会处理此请求。  第三、当处理一个请求的处理者对象集合需要动态地指定时。  使用责任链模式的长处和短处  责任链模式减低了发出命令的对象和处理命令的对象之间的耦合,它允许多与一个的处理者对象根据自己的逻辑来决定哪一个处理者最终处理这个命令。换言之,发出命令的对象只是把命令传给链结构的起始者,而不需要知道到底是链上的哪一个节点处理了这个命令。  显然,这意味着在处理命令上,允许系统有更多的灵活性。哪一个对象最终处理一个命令可以因为由那些对象参加责任链、以及这些对象在责任链上的位置不同而有所不同。  责任链模式的实现  链结构的由来  值得指出的是,责任链模式并不创建出责任链。责任链的创建必须有系统的其它部分完成。  责任链模式减低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。一个链可以是一条线,一个树,也可以是一个环。链的拓扑结构可以是单连通的或多连通的,责任链模式并不指定责任链的拓扑结构。但是责任链模式要求在同一个时间里,命令只可以被传给一个下家(或被处理掉);而不可以传给多于一个下家。在下面的图中,责任链是一个树结构的一部分。图9、责任链是系统已有的树结构的一部分。图中有阴影的对象给出了一个可能的命令传播路径。  责任链的成员往往是一个更大的结构的一部分。比如在前面所讨论的《红楼梦》中击鼓传花的游戏中,所有的成员都是贾府的成员。如果责任链的成员不存在,那么为了使用责任链模式,就必须创建它们;责任链的具体处理者对象可以是同一个具体处理者类的实例。  在Java的1.0版的AWT事件处理模型里,责任链便是视窗上的部件的容器等级结构。  在下面会谈到的Internet Explorer的DHTML的DOM事件处理模型里,责任链则是DOM等级结构本身。  命令的传递  在一个责任链上传递的可能不只有一个命令,而是数个命令。这些命令可以采取抽象化层、具体化层的多态性实现方式,见下图,从而可以将命令对象与责任链上的对象之间的责任分隔开,并将命令对象与传播命令的对象分隔开。图10、多个命令在责任链上的传播。&  当然如果责任链上的传播的命令只有一个、且是固定的命令,那么这个命令不一定要对象化。这就是本节处理击鼓传花游戏里面传来传去的花束的办法。花束代表酒令,可以由一个对象代表;但是本章的处理是过程式的,用对下家对象的next()方法的调用达成。
对象的树结构  在面向对象的技术里,对象的树结构是一个强有力的工具,更是模式理论的一个重要的组成部分,需要应用到符合模式、装饰模式和迭代子模式。  《墨子.天志》说:“庶人竭力从事,未得次己而为政,有士政之,士竭力从事,未得次己而为政,有将军、大夫政之;将军、大夫竭力从事,未得次己而为政,有三公、诸侯政之;三公、诸侯竭力听治,未得次己而为政,有天子政之;天子未得次己而为政,有天政之。”  “次”意为恣意。上面的话就是说,百姓有官吏管治,官吏由将军和士大夫管治,将军和士大夫由三公和诸侯管治,三公和诸侯由天子管治,天子由天管治。图11、墨子论责任和责任链的传播。图中有阴影的对象给出了一个可能的责任链选择。&  当一个百姓提出要求时,此要求会传达到“士”一级,再到“大夫”一级,进而传到“诸侯”一级,“天子”一级,最后到“天”一级.
DHTML中的事件处理浏览器的DOM(Document Object Model)模型中的事件处理均采用责任链模式。本节首先考察Netscape浏览器的DHTML的事件处理,然后再研究Internet Explorer的事件模型。  Netscape的事件模型  Netscape的事件处理机制叫做“事件捕捉”(Event Capturing)。在事件捕捉机制里面,一个事件是从DOM的最高一层向下传播,也就是说,window对象是第一个接到事件的,然后是document对象,如此往下---事件的产生对象反而是最后一个接到事件的。  如果要是一个对象捕获某一个事件,只需要调用captureEvent()方法;如果要使一个对象把某一个事件向下传而不处理此事件,只需要对此对象使用releaseEvents方法即可。下面考察一个简单的事件捕获和传递的例子。图12、一个Netscape的例子。  在这个例子里,有一个textbox和两个button,一个叫做“Capture Event”,单击后会使网页的click事件被捕捉,文字框中的计数会加一;另一个叫做“Release Event”,单击后会使网页的click事件不被捕捉。  使click事件被捕捉需要调用captureEvent()方法,而使click事件不被捕捉需要调用releaseEvent()方法。下面是具体的html和JavaScript代码。
代码清单6、JavaScript和HTML源代码。&  显然,一个事件可以在几个不同的等级上得到处理,这是一个不纯的责任链模式。&  Internet Explorer的事件模型  Internet Explorer处理事件的方式与Netscape既相似又不同。当一个事件发生在Internet Explorer所浏览的网页中时,Internet Explorer会使用DHTML的“Event Bubbling”即事件浮升机制处理此事件。Internet Explorer的DOM模型是html对象等级结构和事件处理机制。在DOM里面,每一个html标示都是一个DOM对象,而每一个DOM对象都可以产生事先定义好的几个事件中的一个(或几个)。这样的一个事件会首先发生在事件所属的对象上,然后向上传播,传到此对象所属的容器对象上,如此等等。因此,事件浮升机制恰恰是事件捕捉机制的相反面。  &在Event Bubbling机制里面,产生事件的对象首先会收到事件。然后,事件会依照对象的等级结构向上传播。比如一个DIV里有一个Form,Form里面又有一个Button,那么当Button的onclick事件产生时,Form的onclick事件代码就会被执行。然后,事件就会传到DIV对象。如果DIV对象的onclick事件有任何代码的话,这代码就会被执行,然后事件继续沿着DOM结构上行。  如果要阻止事件继续向上传播,可以在事件链的任何一个节点上把cancelBubble性质设置成True即可。  Internet Explorer&浏览器几乎为所有的&HTML&标识符都提供了事件句柄,因此Internet Explorer不需要captureEvents()方法和releaseEvents()方法来捕获和释放事件。下面的JavaScript语句指定了document对象的onclick事件的处理方法:
document.onclick = functionN
  而下面的语句则停止了document对象对onclick事件的处理。
document.onclick =
  因为事件处理性质被赋值null,document便没有任何的方法处理此事件。换言之,null值禁止了此对象的事件处理。这种方法可以用到任何的对象和任何的事件上面。当然这一做法不适用于Netscape。  与Netscape中一样,一个事件处理方法可以返还Boolean值。比如,单击一个超链接标记符是否造成浏览器跟进,取决于此超链接标记符的onclick事件是否返还true。  为了显示Internet Explorer中的事件浮升机制,本节特准备了下面的例子。一个Form里面有一个Button,请见下图:图13、一个Internet Explorer的例子。  其HTML代码请见下面:
代码清单7、JavaScript和HTML源代码。&  当myButton的onclick事件发生时,myButton的事件处理首先被激发,从而显示出如下的对话窗:图14、myButton对象的事件处理被激发。  然后事件会象气泡一样浮升到上一级的对象,即myForm对象上。myForm对象的事件处理给出下面的对话窗:图15、myFormn对象的事件处理被激发。  这以后事件继续浮升到更上一级的对象,即body上。这时,document对象的事件处理被激发,并给出下面的对象窗:图16、document对象的事件处理被激发。  这就是事件浮升(Event Bubbling)机制。  显然,这三级对象组成一个责任链,而事件便是命令或请求。当事件沿着责任链传播时,责任链上的对象可以选择处理或不处理此事件;不论事件在某一个等级上是否得到处理,事件都可以停止上浮或继续上浮。这是不纯的责任链模式
DHTML中的事件处理浏览器的DOM(Document Object Model)模型中的事件处理均采用责任链模式。本节首先考察Netscape浏览器的DHTML的事件处理,然后再研究Internet Explorer的事件模型。  Netscape的事件模型  Netscape的事件处理机制叫做“事件捕捉”(Event Capturing)。在事件捕捉机制里面,一个事件是从DOM的最高一层向下传播,也就是说,window对象是第一个接到事件的,然后是document对象,如此往下---事件的产生对象反而是最后一个接到事件的。  如果要是一个对象捕获某一个事件,只需要调用captureEvent()方法;如果要使一个对象把某一个事件向下传而不处理此事件,只需要对此对象使用releaseEvents方法即可。下面考察一个简单的事件捕获和传递的例子。图12、一个Netscape的例子。  在这个例子里,有一个textbox和两个button,一个叫做“Capture Event”,单击后会使网页的click事件被捕捉,文字框中的计数会加一;另一个叫做“Release Event”,单击后会使网页的click事件不被捕捉。  使click事件被捕捉需要调用captureEvent()方法,而使click事件不被捕捉需要调用releaseEvent()方法。下面是具体的html和JavaScript代码。
代码清单6、JavaScript和HTML源代码。&  显然,一个事件可以在几个不同的等级上得到处理,这是一个不纯的责任链模式。&  Internet Explorer的事件模型  Internet Explorer处理事件的方式与Netscape既相似又不同。当一个事件发生在Internet Explorer所浏览的网页中时,Internet Explorer会使用DHTML的“Event Bubbling”即事件浮升机制处理此事件。Internet Explorer的DOM模型是html对象等级结构和事件处理机制。在DOM里面,每一个html标示都是一个DOM对象,而每一个DOM对象都可以产生事先定义好的几个事件中的一个(或几个)。这样的一个事件会首先发生在事件所属的对象上,然后向上传播,传到此对象所属的容器对象上,如此等等。因此,事件浮升机制恰恰是事件捕捉机制的相反面。  &在Event Bubbling机制里面,产生事件的对象首先会收到事件。然后,事件会依照对象的等级结构向上传播。比如一个DIV里有一个Form,Form里面又有一个Button,那么当Button的onclick事件产生时,Form的onclick事件代码就会被执行。然后,事件就会传到DIV对象。如果DIV对象的onclick事件有任何代码的话,这代码就会被执行,然后事件继续沿着DOM结构上行。  如果要阻止事件继续向上传播,可以在事件链的任何一个节点上把cancelBubble性质设置成True即可。  Internet Explorer&浏览器几乎为所有的&HTML&标识符都提供了事件句柄,因此Internet Explorer不需要captureEvents()方法和releaseEvents()方法来捕获和释放事件。下面的JavaScript语句指定了document对象的onclick事件的处理方法:
document.onclick = functionN
  而下面的语句则停止了document对象对onclick事件的处理。
document.onclick =
  因为事件处理性质被赋值null,document便没有任何的方法处理此事件。换言之,null值禁止了此对象的事件处理。这种方法可以用到任何的对象和任何的事件上面。当然这一做法不适用于Netscape。  与Netscape中一样,一个事件处理方法可以返还Boolean值。比如,单击一个超链接标记符是否造成浏览器跟进,取决于此超链接标记符的onclick事件是否返还true。  为了显示Internet Explorer中的事件浮升机制,本节特准备了下面的例子。一个Form里面有一个Button,请见下图:图13、一个Internet Explorer的例子。  其HTML代码请见下面:
代码清单7、JavaScript和HTML源代码。&  当myButton的onclick事件发生时,myButton的事件处理首先被激发,从而显示出如下的对话窗:图14、myButton对象的事件处理被激发。  然后事件会象气泡一样浮升到上一级的对象,即myForm对象上。myForm对象的事件处理给出下面的对话窗:图15、myFormn对象的事件处理被激发。  这以后事件继续浮升到更上一级的对象,即body上。这时,document对象的事件处理被激发,并给出下面的对象窗:图16、document对象的事件处理被激发。  这就是事件浮升(Event Bubbling)机制。  显然,这三级对象组成一个责任链,而事件便是命令或请求。当事件沿着责任链传播时,责任链上的对象可以选择处理或不处理此事件;不论事件在某一个等级上是否得到处理,事件都可以停止上浮或继续上浮。这是不纯的责任链模式
问答题答案  第一题答案、这是一个纯的责任链模式。  首先,在“猪”牌放出之后,每个人都只能要么躲过“猪”牌,要么吃住“猪”牌。“猪”牌便是责任链模式中的请求,四个人便是四个处理者对象,组成责任链。  每一个参加者的行为不仅仅取决于他手中的牌,而且取决于他是否想得“猪”牌。一个想收全红的人,可能会权力揽“猪”牌,一个不想收全红的人,一般不想收“猪”牌,除非他想阻止别人收“猪”牌。因为一旦有人收全红,另外三个人就会复出较大的代价,因此阻止别人收全红的动机,会促使一个参与者主动收“猪”牌。有的时候,放出“猪”牌的人也会想要得“猪”牌而得不到,有的时候放出“猪”牌的人想要害人但却害了自己。  这就是说,到底是四个人中的哪一个人得到“猪”牌是完全动态决定的。  系统的UML结构图如下:图18、纸牌游戏“拱猪”的UML类图。&  由于玩牌的时候,可能有四人位置的任意调换,或者有候补者在旁等待,一旦在任的玩家被淘汰,便可上任。这样四个人组成的牌局是动态变化的。同时因为谁会拿到“猪”牌在每一局均会不同,因此谁会放出“猪”牌也是动态的。  因此,责任链的组成和顺序变不是一成不变的,而是动态的和变化的。  第二题答案、墨子的守城部队的等级结构可以用下面的对象图表示。图17、对象图,显示墨子的守城部队。&  显然,这是一个纯的责任链模式。任何提出申请的兵勇便是客户端,伍长、什长、佰长、大帅和大将是责任链的具体处理者对象。一个申请会在链上传播,直到某一级的有合适的权限的军官处理申请为止。每一个申请必会得到处理,批准或驳回。一个被处理过的申请会按照相反的方向传播,直到传回到发出申请的兵勇手中。  发出申请的士兵在发出申请时根本不知道他的申请会向上传播多少等级。  第三题答案、这是纯的责任链模式。  首先,酒便是请求的代表。每一个酒会的参与者都是一个请求的处理者对象,所有的参加者组成责任链。一个酒杯会漂过每一个参加者,代表一个请求经过每一个请求处理者对象。  每一个酒会的参加者都有可能选择喝掉某一杯酒,或者让酒继续漂向下一个参加者,而且假定所有的酒最后都会被某一个参加者喝掉,因此这是纯的责任链模式。

我要回帖

更多关于 在线拱猪游戏 的文章

 

随机推荐