这几天一直在忙期末考和实训,写笔记的时间也没有多少,不说废话了:
这文主要写两种模式:状态跟策略,主要是因为他们的类图一样,并且比较简单,写在同一篇文章里面容易甄别
状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了他的类
先保留概念的意思,在平常的编程中,如果需要不同的状态,很一般的做法是在你要操作的类里面定义不同的常量代表不同的状态,然后if-else依据不同的状态有不同的实现:
1、你可以想象大量的if-else语句造成的低可读性和低效率
2、其次是你修改这个类的时候很麻烦,增加或删除常量状态可能要逐个修改,这也违反了开闭原则
所谓状态模式,他的通常做法是用一个类去代表一个状态
引用《Head First 设计模式》的糖果机例子:客户通过投币、转动曲柄的方式向糖果机买糖果,类似于普通生活的自动售卖机,那么我们要写代码描述这一过程:
我们有必要把行为和状态分类:
行为:投币、退币、转动曲柄、发放糖果动作
状态:有钱状态、没钱(等待)状态、发放糖果状态、糖果售罄状态
(后面会在另外一篇里写代理模式,例子会根据状态模式的例子扩展,哈,图个方便引用head first的例子,毕竟学生狗经验有限,写不出高质量的例子)
现在我们要做的是在不同的状态改变糖果机的行为、或者不同的行为同时改变状态,针对场景,我们可以用这样的类图描述状态:
后面有一个新的状态是winnerState,他描述了客户在买糖果的时候有十分之一的概率中奖,这里没有列出来,代码会有:
现在已经很清楚地分开了状态跟行为:根据类图的代码:
public interface State {
//投币
public void insertQuarter();
//退币
public void ejectQuarter();
//转动
public void turnCrank();
//发放奖品
public void dispend();
}
public class HasQuarterState implements State {
//我们可以看到状态跟糖果机存在依赖
private GumballMachine gumballMachine;
//中奖的概率事件写在投币状态,因为这是中奖的前一个状态
Random randomWinner = new Random(System.currentTimeMillis());
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
//告诉顾客已经投币,不能再次投币
//这就是状态模式的一个特点:允许对象在内部状态改变时改变他的行为,这个在setState的方法中体现,例如在ejectQuarter()
//而这里是跟ejectQuarter()同性质的行为方法,但是他在HasQuarterState这个状态中不做任何事情,最多只能是提示
//顾客你已经投币了,当然仅仅是相对这个例子来说,如果有其他的场景,并不说明一定是有不干活的行为
@Override
public void insertQuarter() {System.out.println("You cannot inserted another quarter");}
//状态改变时改变环境类的行为
@Override
public void ejectQuarter() {
System.out.println("Quarter returned");
//退币行为的下一个状态自然是等待状态
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
public void turnCrank() {
System.out.println("You turned...");
int winner = randomWinner.nextInt(10);
if(winner==0&&gumballMachine.getCount()>1){
//中奖了,那么把糖果机状态改为中奖状态
gumballMachine.setState(gumballMachine.getWinnerState());
}else{
//否则就是发放奖品状态,状态更换之后便不用再管糖果机的行为
//因为糖果机的行为会委托给下一个状态
gumballMachine.setState(gumballMachine.getSoldState());
}
}
//告诉顾客没有糖果发放
@Override
public void dispend() {System.out.println("no gumball dispended");}
@Override
public String toString() {
return "HasQuarterState";
}
}
public class NoQuarterState implements State {
private GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
public void ejectQuarter() {System.out.println("You haven't inserted a quarter");}
@Override
public void turnCrank() {System.out.println("You turned,but there is no quarter");}
@Override
public void dispend() {System.out.println("You n