1700473346
我们来思考我们的业务,电梯在门敞开状态下就不能上下运行了吗?电梯有没有发生过只有运行没有停止状态呢(从40层直接坠到1层嘛)?电梯故障嘛,还有电梯在检修的时候,可以在stop状态下不开门,这也是正常的业务需求呀,你想想看,如果加上这些判断条件,上面的程序有多少需要修改?虽然这些都是电梯的业务逻辑,但是一个类有且仅有一个原因引起类的变化,单一职责原则,看看我们的类,业务任务上一个小小的增加或改动都使得我们这个电梯类产生了修改,这在项目开发上是有很大风险的。
1700473347
1700473348
既然我们已经发现程序中有以上问题,我们怎么来修改呢?刚刚我们是从电梯的方法以及这些方法执行的条件去分析,现在我们换个角度来看问题。我们来想,电梯在具有这些状态的时候能够做什么事情,也就是说在电梯处于某个具体状态时,我们来思考这个状态是由什么动作触发而产生的,以及在这个状态下电梯还能做什么事情。例如,电梯在停止状态时,我们来思考两个问题:
1700473349
1700473350
❑停止状态是怎么来的,那当然是由于电梯执行了stop方法而来的。
1700473351
1700473352
❑在停止状态下,电梯还能做什么动作?继续运行?开门?当然都可以了。
1700473353
1700473354
我们再来分析其他3个状态,也都是一样的结果,我们只要实现电梯在一个状态下的两个任务模型就可以了:这个状态是如何产生的,以及在这个状态下还能做什么其他动作(也就是这个状态怎么过渡到其他状态),既然我们以状态为参考模型,那我们就先定义电梯的状态接口,类图如图26-4所示。
1700473355
1700473356
1700473357
1700473358
1700473359
图26-4 以状态作为导向的类图
1700473360
1700473361
在类图中,定义了一个LiftState抽象类,声明了一个受保护的类型Context变量,这个是串联各个状态的封装类。封装的目的很明显,就是电梯对象内部状态的变化不被调用类知晓,也就是迪米特法则了(我的类内部情节你知道得越少越好),并且还定义了4个具体的实现类,承担的是状态的产生以及状态间的转换过渡,我们先来看LiftState代码,如代码清单26-7所示。
1700473362
1700473363
代码清单26-7 抽象电梯状态
1700473364
1700473365
public abstract class LiftState{
1700473366
1700473367
//定义一个环境角色,也就是封装状态的变化引起的功能变化
1700473368
1700473369
protected Context context;
1700473370
1700473371
public void setContext(Context_context){
1700473372
1700473373
this.context=_context;
1700473374
1700473375
}
1700473376
1700473377
//首先电梯门开启动作
1700473378
1700473379
public abstract void open();
1700473380
1700473381
//电梯门有开启,那当然也就有关闭了
1700473382
1700473383
public abstract void close();
1700473384
1700473385
//电梯要能上能下,运行起来
1700473386
1700473387
public abstract void run();
1700473388
1700473389
//电梯还要能停下来
1700473390
1700473391
public abstract void stop();
1700473392
1700473393
}
1700473394
1700473395
抽象类比较简单,我们先看一个具体的实现——敞门状态的实现类,如代码清单26-8所示。
[
上一页 ]
[ :1.700473346e+09 ]
[
下一页 ]