使用状态模式来解决分段函数的问题
问题:
有一个函数:
y={ x x<1
| 2x-1 1<=x<10
\ 3x-11 x>=10写一段程序,输入x,输出y
代码实现:
有两种实现方式:
第一种:最简单的办法,使用条ifelse件判断语句来实现:
1 import java.util.Scanner; 2 3 public class Demo { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 System.out.println("请输入一个数:"); 8 Scanner scanner=new Scanner(System.in); 9 int x=scanner.nextInt(); 10 if(x<1){ 11 System.out.println(x); 12 }else if (1<=x&&x<10) { 13 System.out.println(2*x-1); 14 }else { 15 System.out.println(3*x-11); 16 } 17 } 18 19 }
这个方法简单易懂,但是在实际中,这种方法并不是效率最高的,尤其是当面对多个选择判断时。而且在后期维护中也不方便,往往是一处改,处处改,带来不必要的麻烦。
所以建议采用第二种方法
第二种:使用状态模式来实现该问题(当选择条件大于等于三个时,建议使用该方法)
关于状态模式,详情看:https://www.cnblogs.com/wangjiong/p/11249380.html
首先,先写抽象状态类(status):
1 public interface Status { 2 3 //定义不同状态需要实现的方法 4 public boolean s(); 5 6 7 }
其次,再写具体状态类(S1,S2,S3):
1 //第一个具体状态类(S1) 2 public class S1 implements Status{ 3 Context context; 4 5 //初始化 6 public S1(Context context) { 7 // TODO Auto-generated constructor stub 8 this.context=context; 9 } 10 11 //实现具体状态,符合该状态则输出,不符合则返回false,并将状态传递给下一个状态 12 @Override 13 public boolean s() { 14 // TODO Auto-generated method stub 15 if(context.x<1){ 16 System.out.println("**************"); 17 System.out.println(context.x); 18 System.out.println("**************"); 19 }else{ 20 context.setStatus(context.getStatus2()); 21 return false; 22 } 23 return true; 24 } 25 } 26 27 28 29 //第二个具体状态类(S2) 30 public class S2 implements Status{ 31 Context context; 32 33 //初始化 34 public S2(Context context) { 35 // TODO Auto-generated constructor stub 36 this.context=context; 37 } 38 39 //实现具体状态,符合该状态则输出,不符合则返回false,并将状态传递给下一个状态 40 @Override 41 public boolean s() { 42 // TODO Auto-generated method stub 43 if (context.x<10&&context.x>=1) { 44 System.out.println("**************"); 45 System.out.println(2*context.x-1); 46 System.out.println("**************"); 47 } else { 48 context.setStatus(context.getStatus3()); 49 return false; 50 } 51 return true; 52 } 53 } 54 55 56 //第三个具体状态类(S3) 57 public class S3 implements Status{ 58 Context context; 59 60 //初始化 61 public S3(Context context) { 62 // TODO Auto-generated constructor stub 63 this.context=context; 64 } 65 66 //实现具体状态,符合该状态则输出,不符合则返回false,并且输出错误 67 @Override 68 public boolean s() { 69 // TODO Auto-generated method stub 70 if (context.x>=10) { 71 System.out.println("**************"); 72 System.out.println(3*context.x-11); 73 System.out.println("**************"); 74 } else { 75 System.out.println("输入有误!请输入大于等于10的数!"); 76 return false; 77 } 78 return true; 79 } 80 }
然后,是环境类(Context),负责管理具体状态:
1 public class Context { 2 int x; 3 Status status; 4 Status status1; 5 Status status2; 6 Status status3; 7 8 //初始化 9 public Context(int x) { 10 // TODO Auto-generated constructor stub 11 status1=new S1(this); 12 status2=new S2(this); 13 status3=new S3(this); 14 status =status1; 15 this.x =x; 16 } 17 18 //显示状态 19 public boolean show() { 20 return status.s(); 21 } 22 23 //get和set方法 24 public Status getStatus() { 25 return status; 26 } 27 public void setStatus(Status status){ 28 this.status=status; 29 } 30 public Status getStatus1() { 31 return status1; 32 } 33 public void setStatus1(Status status1) { 34 this.status1 = status1; 35 } 36 public Status getStatus2() { 37 return status2; 38 } 39 public void setStatus2(Status status2) { 40 this.status2 = status2; 41 } 42 public Status getStatus3() { 43 return status3; 44 } 45 public void setStatus3(Status status3) { 46 this.status3 = status3; 47 }
最后,是测试类(Test):
1 public class Test { 2 public static void main(String[] args) { 3 4 //获取用户输入的数字 5 System.out.println("请输入一个数:"); 6 Scanner scanner=new Scanner(System.in); 7 int x=scanner.nextInt(); 8 9 //将数字传递给环境类,并获取相应的状态 10 Context context=new Context(x); 11 Status status =new S1(context); 12 13 //将获取到的状态传递给环境类 14 context.setStatus(status); 15 16 //环境类根据所传递过来的状态找到相应的具体状态,并输出 17 while (true) { 18 if(context.show()==true){ 19 System.out.println("结束"); 20 break; 21 } 22 } 23 } 24 }
这样,就使用状态类,解决了分段函数的问题,虽然看上去相比第一种方法麻烦复杂了许多,但是这方便日后对该程序进行升级和维护,而且就算是修改代码,也不会出现一处改,处处改的局面。