职责链模式
需求分析:
你把今天你向经理申请,经理没权利,然后向总监上报,总监也没有权限,向总经理上报的事,写成代码看看,不一定是加薪,也有可能是请假申请.
加薪代码初步
public class Request {
//申请类别
private String type;
//申请内容
private String content;
//加薪金额
private int number;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
public class Manager {
protected String name;
public Manager(String name) {
super();
this.name = name;
}
public void getResult(String managerLevel,Request request) {
if(managerLevel=="经理") {
if(request.getType()=="请假"&&request.getNumber()<=2) {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被批准");
}else {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"我无权处理");
}
}
else if(managerLevel=="总监") {
if(request.getType()=="请假"&&request.getNumber()<=5) {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被批准");
}else {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"我无权处理");
}
}
else if(managerLevel=="总经理") {
if(request.getType()=="请假") {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被批准");
}else if(request.getType()=="加薪"&&request.getNumber()<=500){
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被处理");
}else if(request.getType()=="加薪"&&request.getNumber()>500) {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"再说吧");
}
}
}
}
public class Demo1 {
public static void main(String[] args) {
Manager jingli=new Manager("经理");
Manager zongjian=new Manager("总监");
Manager zongjingli=new Manager("总经理");
Request request=new Request();
request.setType("加薪");
request.setContent("小菜请求加薪");
request.setNumber(1000);
jingli.getResult("经理", request);
zongjian.getResult("总监", request);
zongjingli.getResult("总经理", request);
Request request2=new Request();
request2.setType("请假");
request2.setContent("小菜请假");
request2.setNumber(3);
jingli.getResult("经理", request2);
zongjian.getResult("总监", request2);
zongjingli.getResult("总经理", request2);
}
}
输出结果:
经理: 小菜请求加薪 数量1000我无权处理
总监: 小菜请求加薪 数量1000我无权处理
总经理: 小菜请求加薪 数量1000再说吧
经理: 小菜请假 数量3我无权处理
总监: 小菜请假 数量3被批准
总经理: 小菜请假 数量3被批准
问题描述:
比较长的方法,多条的分支这些其实都是代码的坏味道;比如在Manager类,因为你很难讲里面会不会增加其他的管理类别,比如项目经理,部门经理,人力总监,副总经理等等,那就意味着都需要更改这个类,这个类承担了太多的责任,违背了单一职责原则,增加新的管理类别,需要修改这个类,违背了开放-封闭原则
Manager类可能会增加管理类别,说明这里容易变化,可以把这些公司的管理类别做管理者的子类,这样就可以利用多态来化解分支带来的僵化.
如何解决经理无法上报总监,总监无法上报总经理呢?要想让它们之间有一定的关联,把用户的请求传递,直到解决这个请求为止.可以使用职责链模式
职责链重构
public class Request {
//申请类别
private String type;
//申请内容
private String content;
//加薪金额
private int number;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
public abstract class Manager {
protected String name;
//管理者的上级
protected Manager superior;
public Manager(String name) {
this.name=name;
}
//设置管理者的上级
public void setSuperior(Manager superior) {
this.superior=superior;
}
public abstract void requestApplications(Request request);
}
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if(request.getType()=="请假"&&request.getNumber()<=2) {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被批准");
}
else {
if(superior!=null) {
//其余的申请都需要转到上级
superior.requestApplications(request);
}
}
}
}
public class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if(request.getType()=="请假"&&request.getNumber()<=5) {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被批准");
}
else {
if(superior!=null) {
//其余的申请都需要转到上级
superior.requestApplications(request);
}
}
}
}
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if(request.getType()=="请假") {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被批准");
}else if(request.getType()=="加薪"&&request.getNumber()<=500){
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"被处理");
}else if(request.getType()=="加薪"&&request.getNumber()>500) {
System.out.println(name+": "+request.getContent()+" 数量"+request.getNumber()+"再说吧");
}
}
}
public class Demo {
public static void main(String[] args) {
CommonManager jingli=new CommonManager("经理");
Majordomo zongjian=new Majordomo("总监");
GeneralManager zongjingli=new GeneralManager("总经理");
//设置上级,完全可以根据需求来更改设置
jingli.setSuperior(zongjian);
zongjian.setSuperior(zongjingli);
Request request=new Request();
request.setType("加薪");
request.setContent("小菜请求加薪");
request.setNumber(1000);
//客户端的请求都是由经理发起,但实际谁来决策由具体管理者来处理,客户端并不知道
jingli.requestApplications(request);
Request request2=new Request();
request2.setType("请假");
request2.setContent("小菜请假");
request2.setNumber(3);
//客户端的请求都是由经理发起,但实际谁来决策由具体管理者来处理,客户端并不知道
jingli.requestApplications(request2);
}
}
职责链模式:
使多个对象都有机会处理请求,从而避免请求的发送者和接受者的耦合关系.将这个对象连城一条链,并沿着这条链传递请求,直到有一个对象处理它为止
职责链模式的好处:
①请求者不管哪个对象来处理,反正该请求会被处理;这就使得接受者和发送者都没有对方明确信息,且链中的对象自己也并不知道链的结构.结果是职责链可简化对象的相互连接,它们仅仅需要保持一个指向其后继者的引用,而不需要保持它所有的候选接受者的引用,这也就大大降低了耦合度
②由于是在客户端来定义链的结构,也就是说,我可以随时增加和修改处理一个请求的结构,增加了给对象指派职责的灵活性.但是也要当心,一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理,所以需要事先考虑全面.(这就跟现实中寄信一样,因为地址不对,最终也无法送达)
③解决了原来大量的分支判断造成的难维护和灵活性差的问题
注意:
①你需要事先给每个具体的管理者设置他的上司是哪个类,也就是设置后继者
②需要在每个具体管理者处理请求时,做出判断,是可以处理这个请求,还是必须推卸责任,转移给后继者处理.