请先看下面两段代码
if( conditionA ){
if( conditionA1 ){
}else if( conditionA2 ){
}else{
}
}else if( conditionB ){
}else{
}
switch(type){
case XxEnum.A:
...
case XxEnum.B:
...
case XxEnum.C:
...
}
这类代码在日常工作中再常见不过了,随便翻两页commit记录就能找得到;虽然作为开发人员也深知被压排期,历史代码难重构的痛,但还是要承认这就是我们引入的bad smell
,它难阅读、难维护、还面向过程…
但还是会有一半以上的开发人员会继续这么做,原因很简单,这么做它快啊;能早几个小时完成工作,早点下班回家它不香么… 确实,短期内可以快速解决问题完成需求,但长此以往项目会变得越来越难以维护,直到它变成一坨屎山,没人愿意碰没人敢碰…
所以,开发人员有义务也有责任,在它变成屎山之前将它进行重构,毕竟它好我也好;那么有没有什么好方式能够快速重构此类代码呢?有没有合适的设计模式可以帮助我呢?
在此抛砖引玉介绍三种设计模式,策略模式、责任链模式、状态模式;
In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use. --from wiki
策略模式
是针对一组算法,将具体每种算法封装到单独的类中,使它们可以彼此进行替换,对客户端隐藏具体细节;
下面就一个简单地支付方式的例子,使用策略模式
进行演示;
public static void main(String[] args) {
switch(args[0]){
case "Alipay":
System.out.println("paying by Alipay...");
break;
case "WechatPay":
System.out.println("paying by WechatPay...");
break;
default:
throw new IllegalArgumentException("no such payment method");
}
}
项目初期,系统支付依赖于阿里pay和微信pay,会出现类似上面的代码;但是现在随着业务的发展,要支持更多的支付手段,就不得不添加新的switch/if-else
…
使用策略模式
进行重构;
public interface Payment {
public void pay(double amount);
}
public class Alipay implements Payment{
@Override
public void pay(double amount) {
System.out.println("paying by Alipay...");
}
}
public class WechatPay implements Payment{
@Override
public void pay(double amount) {
System.out.println("paying by WechatPay...");
}
}
public class JDPay implements Payment{
@Override
public void pay(double amount) {
System.out.println("paying by brother dong...");
}
}
public class PaymentContext {
private Payment payment;
public PaymentContext(String paymentType){
switch(paymentType){
case "Alipay":
payment = new Alipay();
break;
case "WechatPay":
payment = new WechatPay();
break;
case "JDPay":
payment = new JDPay();
break;
default:
throw new IllegalArgumentException("no such payment method");
}
}
public void pay(double amount){
payment.pay(amount);
}
}
可以看到,虽然最后在简单工厂
内还是有条件判断,但是已经好了很多;
In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain. Thus, the chain of responsibility is an object oriented version of the if… else if… else if… else… endif idiom, with the benefit that the condition–action blocks can be dynamically rearranged and reconfigured at runtime.
说人话 责任链模式
,为请求创建一条处理链路,对请求的发起方和处理方进行解耦;
同样使用一个简单请假例子,来解释责任链模式
的使用;
public class App {
public static void main(String[] args) {
int days = Integer.parseInt(args[0]);
if(days < 3){
System.out.println("team leader approve");
}else if(days <= 5){
System.out.println("department leader approve");
}else{
System.out.println("boss approved");
}
}
}
一个请假场景,时间小于3天tl审批即可,小于等于5天的需要部门领导审批,其他的需要boss进行审批;如果公司设立的HRBP,想让HRBP在boss介入前,负责1个月假期的审批,只能维护上述条件表达式,添加if-else/switch
;
使用责任链模式
进行重构:
@Data
public abstract class Approver {
private Approver successorApprover;
public abstract void approve(int days);
}
public class TeamLeader extends Approver{
@Override
public void approve(int days) {
if(days < 3){
System.out.println("team leader approve");
}else{
getSuccessorApprover().approve(days);
}
}
}
public class DepartmentLeader extends Approver{
@Override
public void approve(int days) {
if(days <= 5){
System.out.println("department leader approve");
}else{
getSuccessorApprover().approve(days);
}
}
}
public class Hrbp extends Approver{
@Override
public void approve(int days) {
if(days <= 31){
System.out.println("hrbp approve");
}else{
getSuccessorApprover().approve(days);
}
}
}
public class Boss extends Approver{
@Override
public void approve(int days) {
System.out.println("boss not happy...");
}
}
public class App {
public static void main(String[] args) {
Approver teamLeader = new TeamLeader();
Approver departmentLeader = new DepartmentLeader();
Approver hrbp = new Hrbp();
Approver boss = new Boss();
teamLeader.setSuccessorApprover(departmentLeader);
departmentLeader.setSuccessorApprover(hrbp);
hrbp.setSuccessorApprover(boss);
teamLeader.approve(100);
}
}
没有了烦人的if-else
,同时整个链路也十分清晰;
状态模式
:类的行为随着它状态的改变而改变;
public class App {
public static void main(String[] args) {
switch(args[0]){
case "unlock":
System.out.println("unlock qingju");
break;
case "ride":
System.out.println("ride qingju");
break;
case "park":
System.out.println("park qingju");
break;
case "lock":
System.out.println("lock qingju");
break;
default:
throw new IllegalArgumentException("no such action");
}
}
}
对于骑共享单车的同学们来说,一般的对于单车有以上四类操作,解锁、骑行、停车、锁车,很容易会用if-else
来解决单车处于不同状态时的不同行为;但是如果要增加新的状态或动作,只能维护条件表达式,新增if-else
代码块;
那么使用状态模式
来进行重构:
public interface BicycleState {
public void handleRequest(BicycleContext bicycleContext);
}
public class UnlockBicycle implements BicycleState{
@Override
public void handleRequest(BicycleContext bicycleContext) {
System.out.println("unlock qingju");
bicycleContext.setBicycleState(new RideBicycle());
bicycleContext.request();
}
}
public class RideBicycle implements BicycleState{
@Override
public void handleRequest(BicycleContext bicycleContext) {
System.out.println("ride qingju");
bicycleContext.setBicycleState(new ParkBicycle());
bicycleContext.request();
}
}
public class ParkBicycle implements BicycleState{
@Override
public void handleRequest(BicycleContext bicycleContext) {
System.out.println("park qingju");
bicycleContext.setBicycleState(new LockBicycle());
bicycleContext.request();
}
}
public class LockBicycle implements BicycleState{
@Override
public void handleRequest(BicycleContext bicycleContext) {
System.out.println("lock qingju");
System.out.println("done");
}
}
此时,如果想要新增状态,只需要实现接口即可;
以上抛砖引玉的介绍了三种设计模式来摆脱条件表达式,如果有补充还请留言赐教 共同进步,非常感谢!