一位女性在结婚之前要听从于父亲,结婚之后要听从于丈夫,如果丈夫死了还要听从于儿子。作为父亲、丈夫或儿子,只有两种选择:要不承担起责任来,允许她或不允许她逛街;要不就让她请示下一个人,这是整个社会体系的约束。
下面来看如何通过程序来实现“三从”,需求很简单:通过程序描述一下古代妇女的“三从”制度。
对应的类图:IHandler是三个有决策权对象的接口,IWomen是女性的代码
① IWomen 接口
public interface IWomen {
/**
* 获得个人状况
*
* @return 结婚了还是没结婚、丈夫是否在世
*/
int getType();
/**
* 获得个人请示
* @return 你要干什么?出去逛街?约会?还是看电影?
*/
String getRequest();
}
② Women 实现类
@NoArgsConstructor
@AllArgsConstructor
public class Women implements IWomen {
/*
* 通过一个int类型的参数来描述妇女的个人状况
* 1--未出嫁
* 2--出嫁
* 3--夫死
*/
private int type = 0;
//妇女的请示
private String request = "";
@Override
public int getType() {
return type;
}
@Override
public String getRequest() {
return request;
}
}
③ IHandler 接口
public interface IHandler {
/**
* 一个女性(女儿、妻子或者母亲)要求逛街,你要处理这个请求
*/
public void HandleMessage(IWomen women);
}
④ Father 实现类
public class Father implements IHandler {
/**
* 未出嫁的女儿来请示父亲
*/
public void HandleMessage(IWomen women) {
System.out.println("女儿的请示是:" + women.getRequest());
System.out.println("父亲的答复是:同意");
}
}
⑤ Husband 实现类
public class Husband implements IHandler {
/**
* 妻子向丈夫请示
*/
public void HandleMessage(IWomen women) {
System.out.println("妻子的请示是:" + women.getRequest());
System.out.println("丈夫的答复是:同意");
}
}
⑥ Son 实现类
public class Son implements IHandler {
/**
* 母亲向儿子请示
*/
public void HandleMessage(IWomen women) {
System.out.println("母亲的请示是:" + women.getRequest());
System.out.println("儿子的答复是:同意");
}
}
⑦ Client 测试类
public class Client {
public static void main(String[] args) {
//随机挑选几个女性
Random rand = new Random();
ArrayList<IWomen> arrayList = new ArrayList();
for (int i = 0; i < 5; i++) {
arrayList.add(new Women(rand.nextInt(4), "我要出去逛街"));
}
//定义三个请示对象
IHandler father = new Father();
IHandler husband = new Husband();
IHandler son = new Son();
for (IWomen women : arrayList) {
if (women.getType() == 1) {
//未结婚少女,请示父亲
System.out.println("\n--------女儿向父亲请示-------");
father.HandleMessage(women);
} else if (women.getType() == 2) {
//已婚少妇,请示丈夫
System.out.println("\n--------妻子向丈夫请示-------");
husband.HandleMessage(women);
} else if (women.getType() == 3) {
//母亲请示儿子
System.out.println("\n--------母亲向儿子请示-------");
son.HandleMessage(women);
} else {
//暂时什么也不做
}
}
}
}
上述代码实现存在职责界定不清晰,代码臃肿,耦合过重,异常情况欠考虑等问题。
女性提出一个请示,必然要获得一个答复,甭管是同意还是不同意,总之是要一个答复的,而且这个答复是唯一的,不能说是父亲作出一个决断,而丈夫也作出了一个决断,也即是请示传递出去,必然有一个唯一的处理人给出唯一的答复。
我们可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就作出回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去天国报道了,那就由儿子来处理这个请求。
父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回应;要么把请求转发到后序环节。
三个实现类Father、Husband、Son只要实现构造函数和父类中的抽象方法response就可以了,具体由谁处理女性提出的请求,都已经转移到了Handler抽象类中。
① Handler 抽象类
public abstract class Handler {
//可以处理的请求的级别
public final static int FATHER_LEVEL_REQUEST = 1;
public final static int HUSBAND_LEVEL_REQUEST = 2;
public final static int SON_LEVEL_REQUEST = 3;
//能处理的级别
private int level = 0;
//责任传递,下一个人责任人是谁
private Handler nextHandler;
//每个类都要说明一下自己能处理哪些请求
public Handler(int _level) {
this.level = _level;
}
public final void HandleMessage(IWomen women) {
if (women.getType() == this.level) {
//一个女性要求逛街,你要处理这个请求
this.response(women);
} else {
//有后续环节,才把请求往后递送
if (this.nextHandler != null) {
this.nextHandler.HandleMessage(women);
} else {
//已经没有后续处理人了,不用处理了
System.out.println("---没地方请示了,按不同意处理---\n");
}
}
}
/*
* 如果不属于你处理的请求,你应该让她找下一个环节的人,如女儿出嫁了,
* 还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示
*/
public void setNext(Handler _handler) {
this.nextHandler = _handler;
}
//有请示那当然要回应
protected abstract void response(IWomen women);
}
其实在这里也用到模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应,如果已经达到环节结尾,则直接做不同意处理。基本方法response需要各个实现类实现,每个实现类只要实现两个职责:一是定义自己能够处理的等级级别;二是对请求做出回应。
② Father 子类
public class Father extends Handler {
//父亲只处理女儿的请求
public Father() {
super(Handler.FATHER_LEVEL_REQUEST);
}
//父亲的答复
protected void response(IWomen women) {
System.out.println("--------女儿向父亲请示-------");
System.out.println(women.getRequest());
System.out.println("父亲的答复是:同意\n");
}
}
③ Husband 子类
public class Husband extends Handler {
//丈夫只处理妻子的请求
public Husband() {
super(Handler.HUSBAND_LEVEL_REQUEST);
}
//丈夫请示的答复
protected void response(IWomen women) {
System.out.println("--------妻子向丈夫请示-------");
System.out.println(women.getRequest());
System.out.println("丈夫的答复是:同意\n");
}
}
④ Son 子类
public class Son extends Handler {
//儿子只处理母亲的请求
public Son() {
super(Handler.SON_LEVEL_REQUEST);
}
//儿子的答复
protected void response(IWomen women) {
System.out.println("--------母亲向儿子请示-------");
System.out.println(women.getRequest());
System.out.println("儿子的答复是:同意\n");
}
}
这三个类都很简单,构造方法是必须实现的,父类框定子类必须有一个显式构造函数,子类不实现编译不通过。通过构造方法我们设置了各个类能处理的请求类型,Father只能处理请求类型为1(也就是女儿)的请求;Husband只能处理请求类型类为2(也就是妻子)的请求,儿子只能处理请求类型为3(也就是母亲)的请求,那如果请求类型为4的该如何处理呢?在Handler中我们已经判断了,如何没有相应的处理者(也就是没有下一环节),则视为不同意。
⑤ Women 实现类
public class Women implements IWomen {
/*
* 通过一个int类型的参数来描述妇女的个人状况
* 1--未出嫁
* 2--出嫁
* 3--夫死
*/
private int type = 0;
//妇女的请示
private String request = "";
//构造函数传递过来请求
public Women(int type , String request) {
this.type = type;
//为了便于显示,在这里做了点处理
switch (this.type) {
case 1:
this.request = "女儿的请求是:" + request;
break;
case 2:
this.request = "妻子的请求是:" + request;
break;
case 3:
this.request = "母亲的请求是:" + request;
default:
}
}
//获得自己的状况
public int getType() {
return this.type;
}
//获得妇女的请求
public String getRequest() {
return this.request;
}
}
⑥ Client 测试类
public class Client {
public static void main(String[] args) {
//随机挑选几个女性
Random rand = new Random();
ArrayList<IWomen> arrayList = new ArrayList();
for (int i = 0; i < 5; i++) {
arrayList.add(new Women(rand.nextInt(4), "我要出去逛街"));
}
//定义三个请示对象
Handler father = new Father();
Handler husband = new Husband();
Handler son = new Son();
//设置请示顺序
father.setNext(husband);
husband.setNext(son);
for (IWomen women : arrayList) {
father.HandleMessage(women);
}
}
}
在Client中设置请求的传递顺序,先向父亲请示,不是父亲应该解决的问题,则由父亲传递到丈夫类解决,若不是丈夫类解决的问题则传递到儿子类解决,最终的结果必然有一个返回。
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果:
① Handler 抽象类
public abstract class Handler {
private Handler nextHandler;
//每个处理者都必须对请求做出处理
//被final修改的抽象方法不能被继承
public final Response handleMessage(Request request) {
Response response = null;
//判断是否是自己的处理级别
if (this.getHandlerLevel().equals(request.getRequestLevel())) {
response = this.echo(request);
} else {
//不属于自己的处理级别
//判断是否有下一个处理者
if (this.nextHandler != null) {
response = this.nextHandler.handleMessage(request);
} else {
//没有适当的处理者,业务自行处理
}
}
return response;
}
//设置下一个处理者是谁
public void setNext(Handler _handler) {
this.nextHandler = _handler;
}
//每个处理者都有一个处理级别
protected abstract Level getHandlerLevel();
//每个处理者都必须实现处理任务
protected abstract Response echo(Request request);
}
② ConcreteHandler1 处理者子类
public class ConcreteHandler1 extends Handler {
/**
* 定义自己的处理逻辑
*/
protected Response echo(Request request) {
//完成处理逻辑
return null;
}
/**
* 设置自己的处理级别
*/
protected Level getHandlerLevel() {
//设置自己的处理级别
return null;
}
}
③ ConcreteHandler2 处理者子类
public class ConcreteHandler2 extends Handler {
/**
* 定义自己的处理逻辑
*/
protected Response echo(Request request) {
//完成处理逻辑
return null;
}
/**
* 定义自己的处理逻辑
*/
protected Level getHandlerLevel() {
//设置自己的处理级别
return null;
}
}
④ ConcreteHandler3 处理者子类
public class ConcreteHandler3 extends Handler {
/**
* 定义自己的处理逻辑
*/
protected Response echo(Request request) {
//完成处理逻辑
return null;
}
/**
* 设置自己的处理级别
*/
protected Level getHandlerLevel() {
//设置自己的处理级别
return null;
}
}
⑤ Client 测试类
public class Client {
public static void main(String[] args) {
//声明所有的处理节点
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
//设置链中的阶段顺序1-->2-->3
handler1.setNext(handler2);
handler2.setNext(handler3);
//提交请求,返回结果
Response response = handler1.handlerMessage(new Request());
}
}
责任链在实际的项目中使用也是比较多的,我曾经做过这样一个项目,界面上有一个用户注册功能,注册用户分两种,一种是VIP用户,也就是在该单位办理过业务的,一种是普通用户,一个用户的注册要填写一堆信息,VIP用户只比普通用户多了一个输入项:VIP序列号。注册后还需要激活,VIP和普通用户的激活流程也是不同的,VIP是自动发送邮件到用户的邮箱中就算激活了,普通用户要发送短信才能激活,为什么呢?获得手机号码以后好发广告短信啊!项目组就采用了责任链模式,甭管从前台传递过来的是VIP用户信息还是普通用户信息,统一传递到一个处理入口,通过责任链来完成任务的处理。