描述
场景:
1)传物品游戏:有一个球,若干人围成一个圈,音乐响起,然后要快速的传递给下一个人,当音乐突然停止的时候,如果球在自己手中表示失败(假定所有人都按规矩正常传球),淘汰
2)商品打折活动:商店在搞活动促销(满1000元打五折,满500打七折,满300打八折,满100打九折)。你去到商店买东西,经过一番挑选,也不确定最终会消费多少(意味着不确定最后能够打几折),只有在你选好东西算总价(结算)的时候才知道。
3)报销:公司报销流程,超过500只需要直接领导人签字,500–2000部门经理签字,2000–5000要总经理签字,5000以上要总经理签字
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止,或者要么不处理。需要注意的是,在职责链模式中,不一定所有请求都会被处理,可能是不处理
1)在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
2)请求在这条链上传递,直到链上的某一个对象处理此请求为止。
3)发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
- 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
- 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求。
职责链模式的优点:
- 降低耦合度 :该模式使得一个对象无需知道是其他哪一个对象处理其请求。对象仅需知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。
- 职责链可简化对象的相互连接 : 结果是,职责链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
- 增强了给对象指派职责( R e s p o n s i b i l i t y )的灵活性 :当在对象中分派职责时,职责链给你更多的灵活性。你可以通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。你可以将这种机制与静态的特例化处理对象的继承机制结合起来使用。
- 增加新的请求处理类很方便
职责链模式的缺点:
- 不能保证请求一定被接收。既然一个请求没有明确的接收者,那么就不能保证它一定会被处理 —该请求可能一直到链的末端都得不到处理。一个请求也可能因该链没有被正确配置而得不到处理。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用。
贴代码:
定义一个抽象类来管理下一个流转职责流转
/**
* @Description 职责链模式
* 统一TotalHandler抽象类
* 业务场景:
* 顾客去买东西,商家提供了几种折扣活动
* 1)满100元,打九折
* 2)满300元,打八折
* 3)满500元,打七折
* 4)1000元以上,五折
* 普通代码为:
* if(total >= 1000) {
* total *= 0.5
* } else if(total >= 500) {
* total *= 0.7
* } else if(total >= 300) {
* total *= 0.8
* } else if(total >= 100) {
* total *= 0.9
* }
* @Date 2017/7/15 22:34
* @Autor Nick
*/
public abstract class TotalHandler {
public TotalHandler nextHandler;
public void setNextHandler(TotalHandler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 计算付款总价
* @param total
*/
public abstract float paymentTotal(float total);
}
满1000元,打五折:
/**
* @Description 满千元,打五折
* @Date 2017/7/15 22:50
* @Since v1.7
* @Autor Nick
*/
public class FiveDiscountHandler extends TotalHandler {
/**
* 计算付款总价
*
* @param total
*/
@Override
public float paymentTotal(float total) {
if(total >= 1000) {
return total *= 0.5;
} else {
return nextHandler != null ? nextHandler.paymentTotal(total) : total;
}
}
}
满500,打七折:
/**
* @Description 满伍佰元,打七折
* @Date 2017/7/15 22:58
* @Since v1.7
* @Autor Nick
*/
public class SevenDiscountHandler extends TotalHandler {
/**
* 计算付款总价
*
* @param total
*/
@Override
public float paymentTotal(float total) {
if(total >= 500) {
return total *= 0.7;
} else {
return nextHandler != null ? nextHandler.paymentTotal(total) : total;
}
}
}
满300元,打八折:
/**
* @Description 满3佰元,打八折
* @Date 2017/7/15 22:59
* @Since v1.7
* @Autor Nick
*/
public class EightDiscountHandler extends TotalHandler {
/**
* 计算付款总价
*
* @param total
*/
@Override
public float paymentTotal(float total) {
if(total >= 300) {
return total *= 0.8;
} else {
return nextHandler != null ? nextHandler.paymentTotal(total) : total;
}
}
}
满100元,打九折:
/**
* @Description 满1佰元,打九折
* @Date 2017/7/15 23:00
* @Since v1.7
* @Autor Nick
*/
public class NineDiscountHandler extends TotalHandler {
/**
* 计算付款总价
*
* @param total
*/
@Override
public float paymentTotal(float total) {
if(total >= 100) {
return total *= 0.9;
} else {
return nextHandler != null ? nextHandler.paymentTotal(total) : total;
}
}
}
编写测试类:
/**
* @Description 测试类
* @Date 2017/7/15 23:01
* @Since v1.7
* @Autor Nick
*/
public class MainTest {
public static void main(String[] args) {
//定义规则
TotalHandler fiveDiscount = new FiveDiscountHandler(); //打五折
TotalHandler sevenDiscount = new SevenDiscountHandler(); //打七折
TotalHandler eightDiscount = new EightDiscountHandler(); //打八折
TotalHandler nineDiscount = new NineDiscountHandler(); //打九折
//衔接各责任链,指定下一个处理情况
fiveDiscount.setNextHandler(sevenDiscount);
sevenDiscount.setNextHandler(eightDiscount);
eightDiscount.setNextHandler(nineDiscount);
//此处必须是使用fiveDiscount开始,表示从五折开始,如果换成别的,就是对应的if else也不一样
System.out.println("购买2000元打折后需支付金额为:" + fiveDiscount.paymentTotal(2000)); //1000.0
System.out.println("购买358元打折后需支付金额为:" + fiveDiscount.paymentTotal(358)); //286.4
System.out.println("购买843元打折后需支付金额为:" + fiveDiscount.paymentTotal(843)); //590.1
System.out.println("购买80元打折后需支付金额为:" + fiveDiscount.paymentTotal(80)); //80.0
System.out.println("购买221元打折后需支付金额为:" + fiveDiscount.paymentTotal(221)); //198.9
}
}