概述
Java中设计模式是为了解决问题,不要为了练习而强行在工程中应用,让原本100行代码就能实现的功能,写了1000行代码,对错不说,增加了代码的复杂度。下面一起看看责任链设计模式,进行练习。
责任链模式,一种行为设计模式,允许你将请求沿着处理者链进行发送,收到请求后,每个处理者均可以对请求进行处理,或将其传递给链上的下个处理者。
责任链模式使用的场景非常多,如审批流程,过滤器filter,在这些场景若不使用设计模式,那么当需求有所改变时,就会使得代码臃肿或难以维护。
实例
一个闯关游戏,进入下一关的条件时上一关的分数要高于XX分:
- 3个关卡;
- 若第一关得分大于等于80分则进入第二关;
- 若第二关得分大于等于90分则进入第三关;
1、最初写法
public class FirstPassHandler {
public int handler(){
System.out.println("第一关-->FirstPassHandler");
return 80;
}
}
public class SecondPassHandler {
public int handler(){
System.out.println("第二关-->SecondPassHandler");
return 90;
}
}
public class ThirdPassHandler {
public int handler(){
System.out.println("第三关-->ThirdPassHandler,这是最后一关啦");
return 95;
}
}
测试调用
public static void main(String[] args) {
//第一关
FirstPassHandler firstPassHandler = new FirstPassHandler();
//第二关
SecondPassHandler secondPassHandler = new SecondPassHandler();
//第三关
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
int firstScore = firstPassHandler.handler();
//第一关的分数大于等于80则进入第二关
if(firstScore >= 80){
int secondScore = secondPassHandler.handler();
//第二关的分数大于等于90则进入第二关
if(secondScore >= 90){
thirdPassHandler.handler();
}
}
}
如果这个游戏有100关,那么调用的代码可能是这样子
if (1关) {
//
if (2关) {
//
if (3关) {
//
if (4关) {
//
if (5关) {
//
...
}
}
}
}
}
这样子的代码不仅冗余,并且当跳转关卡时对代码的改动非常大,风险加大。
2、初步改造
通过链表将每一关连接起来,形成责任链的方式,第一关通过后进入第二关,第二个通过后进入第三关,这样调用就不需要多重if判断了。
public class FirstPassHandler {
/**
* 第一关的下一关是 第二关
*/
private SecondPassHandler secondPassHandler;
public void setSecondPassHandler(SecondPassHandler secondPassHandler) {
this.secondPassHandler = secondPassHandler;
}
/**
* 本关卡游戏得分
* @return
*/
private int play(){
return 80;
}
public int handler(){
System.out.println("第一关-->FirstPassHandler");
if(play() >= 80){
//分数>=80 并且存在下一关才进入下一关
if(this.secondPassHandler != null){
return this.secondPassHandler.handler();
}
}
return 80;
}
}
public class SecondPassHandler {
/**
* 第二关的下一关是 第三关
*/
private ThirdPassHandler thirdPassHandler;
public void setThirdPassHandler(ThirdPassHandler thirdPassHandler) {
this.thirdPassHandler = thirdPassHandler;
}
/**
* 本关卡游戏得分
* @return
*/
private int play(){
return 90;
}
public int handler(){
System.out.println("第二关-->SecondPassHandler");
if(play() >= 90){
//分数>=90 并且存在下一关才进入下一关
if(this.thirdPassHandler != null){
return this.thirdPassHandler.handler();
}
}
return 90;
}
}
public class ThirdPassHandler {
/**
* 本关卡游戏得分
* @return
*/
private int play(){
return 95;
}
/**
* 这是最后一关,因此没有下一关
*/
public int handler(){
System.out.println("第三关-->ThirdPassHandler,这是最后一关啦");
return play();
}
}
测试调用
public static void main(String[] args) {
//第一关
FirstPassHandler firstPassHandler = new FirstPassHandler();
//第二关
SecondPassHandler secondPassHandler = new SecondPassHandler();
//第三关
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
//第一关的下一关是第二关
firstPassHandler.setSecondPassHandler(secondPassHandler);
//第二关的下一关是第三关
secondPassHandler.setThirdPassHandler(thirdPassHandler);
//说明:因为第三关是最后一关,因此没有下一关
//开始调用第一关 每一个关卡是否进入下一关卡 在每个关卡中判断
firstPassHandler.handler();
}
虽然连接起来了,但每个关卡中都有下一关卡的成员变量,形成链很不方便,扩展性不好。
3、责任链改造
每个关卡中都有下一关卡的成员变量,且是不一样的,可以在关卡上抽象出一个父类或接口,然后每个具体的关卡去继承或实现。
- 抽象处理者角色:定义一个请求处理的接口,包含抽象处理方法和一个后继连接;
- 具体处理者角色:实现抽象处理者的处理方法,判断是否处理本次请求,若可以则处理,否则将该请求转给后继者;
- 测试调用角色:创建处理链,并向链头的具体处理者对象提交请求,不必关心处理细节和请求的传递过程;
public abstract class AbstractHandler {
/**
* 下一关用当前抽象类来接收
*/
protected AbstractHandler next;
public void setNext(AbstractHandler next) {
this.next = next;
}
public abstract int handler();
}
public class FirstPassHandler extends AbstractHandler{
private int play(){
return 80;
}
@Override
public int handler(){
System.out.println("第一关-->FirstPassHandler");
int score = play();
if(score >= 80){
//分数>=80 并且存在下一关才进入下一关
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class SecondPassHandler extends AbstractHandler{
private int play(){
return 90;
}
@Override
public int handler(){
System.out.println("第二关-->SecondPassHandler");
int score = play();
if(score >= 90){
//分数>=90 并且存在下一关才进入下一关
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class ThirdPassHandler extends AbstractHandler{
private int play(){
return 95;
}
@Override
public int handler(){
System.out.println("第三关-->ThirdPassHandler");
int score = play();
if(score >= 95){
//分数>=95 并且存在下一关才进入下一关
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
测试调用
public static void main(String[] args) {
//第一关
FirstPassHandler firstPassHandler = new FirstPassHandler();
//第二关
SecondPassHandler secondPassHandler = new SecondPassHandler();
//第三关
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
// 和上面没有更改的客户端代码相比,只有这里的set方法发生变化,其他都是一样的
//第一关的下一关是第二关
firstPassHandler.setNext(secondPassHandler);
//第二关的下一关是第三关
secondPassHandler.setNext(thirdPassHandler);
//说明:因为第三关是最后一关,因此没有下一关
//从第一个关卡开始
firstPassHandler.handler();
}
4、责任链工厂改造
对于上面的请求链,可以把这个关系维护在配置文件或一个枚举类中。
上一个改造中的抽象类和实现类如上,增加业务链的实体、枚举、链工厂等。
public class PassEntity {
private String name;
private String conference;
private Integer handlerId;
private Integer preHandlerId;
private Integer nextHandlerId;
public PassEntity(String name, String conference, Integer handlerId, Integer preHandlerId, Integer nextHandlerId) {
this.name = name;
this.conference = conference;
this.handlerId = handlerId;
this.preHandlerId = preHandlerId;
this.nextHandlerId = nextHandlerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getConference() {
return conference;
}
public void setConference(String conference) {
this.conference = conference;
}
public Integer getHandlerId() {
return handlerId;
}
public void setHandlerId(Integer handlerId) {
this.handlerId = handlerId;
}
public Integer getPreHandlerId() {
return preHandlerId;
}
public void setPreHandlerId(Integer preHandlerId) {
this.preHandlerId = preHandlerId;
}
public Integer getNextHandlerId() {
return nextHandlerId;
}
public void setNextHandlerId(Integer nextHandlerId) {
this.nextHandlerId = nextHandlerId;
}
}
public enum PassEnum {
// 拦截者名称 全限定类名 handlerId preHandlerId nextHandlerId
FIRST_HANDLER(new PassEntity("first过滤", "com.FirstPassHandler", 1, null, 2)),
SECOND_HANDLER(new PassEntity("second过滤", "com.SecondPassHandler", 2, 1, 3)),
THIRD_HANDLER(new PassEntity("third过滤", "com.ThirdPassHandler", 3, 2, null)),
;
PassEntity passEntity;
public PassEntity getPassEntity() {
return passEntity;
}
PassEnum(PassEntity passEntity) {
this.passEntity = passEntity;
}
}
public interface Pass {
/**
* 根据 handlerId 获取配置项
* @param handlerId
* @return
*/
PassEntity getPassEntity(Integer handlerId);
/**
* 获取第一个处理者
* @return
*/
PassEntity getFirstPassEntity();
}
public class PassImpl implements Pass {
/**
* 初始化,将枚举中配置的handler初始化到map中,方便获取
*/
private static Map<Integer, PassEntity> passEntityMap = new HashMap<>();
static {
PassEnum[] values = PassEnum.values();
for (PassEnum value : values) {
PassEntity passEntity = value.getPassEntity();
passEntityMap.put(passEntity.getHandlerId(), passEntity);
}
}
@Override
public PassEntity getPassEntity(Integer handlerId) {
return passEntityMap.get(handlerId);
}
@Override
public PassEntity getFirstPassEntity() {
for (Map.Entry<Integer, PassEntity> entry : passEntityMap.entrySet()) {
PassEntity value = entry.getValue();
// 没有上一个handler的就是第一个
if (value.getPreHandlerId() == null) {
return value;
}
}
return null;
}
}
工厂,根据枚举类动态形成一条调用链。
public class PassEnumHandlerFactory {
private static Pass pass = new PassImpl();
/**
* 提供静态方法,获取第一个handler
* @return
*/
public static AbstractPassHandler getFirstPassHandler() {
PassEntity firstPassEntity = pass.getFirstPassEntity();
AbstractPassHandler firstAbstractPassHandler = newPassHandler(firstPassEntity);
if (firstAbstractPassHandler == null) {
return null;
}
PassEntity tempPassEntity = firstPassEntity;
Integer nextHandlerId = null;
AbstractPassHandler tempAbstractPassHandler = firstAbstractPassHandler;
// 迭代遍历所有handler,以及将它们链接起来
while ((nextHandlerId = tempPassEntity.getNextHandlerId()) != null) {
PassEntity passEntity = pass.getPassEntity(nextHandlerId);
AbstractPassHandler abstractPassHandler = newPassHandler(passEntity);
tempAbstractPassHandler.setNext(abstractPassHandler);
tempAbstractPassHandler = abstractPassHandler;
tempPassEntity = passEntity;
}
// 返回第一个handler
return firstAbstractPassHandler;
}
/**
* 反射实体化具体的处理者
* @param firstPassEntity
* @return
*/
private static AbstractPassHandler newPassHandler(PassEntity firstPassEntity) {
// 获取全限定类名
String className = firstPassEntity.getConference();
try {
// 根据全限定类名,加载并初始化该类,即会初始化该类的静态段
Class<?> clazz = Class.forName(className);
return (AbstractPassHandler) clazz.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
测试调用
public static void main(String[] args) {
AbstractPassHandler firstPassHandler = PassEnumHandlerFactory.getFirstPassHandler();
firstPassHandler.handler();
}
责任链模式还需深入理解其应用场景,应用于工程中解决实际问题才是关键,努力吧,少年。
最后
以上就是动听花卷为你收集整理的Java设计模式之责任链模式练习的全部内容,希望文章能够帮你解决Java设计模式之责任链模式练习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复