状态模式之微波炉

作者 Lin Wait For Li 日期 2017-03-15
状态模式之微波炉

今天因为工作室组长去面试了CVTE,然后被问了设计微波炉功能。现在想向大家展示自己的思路。

题目要求

设计微波炉功能,带皮不能加热,加热时不能打开,要求可扩展性。

分析问题

寻找具有状态的本身实体对象,这里就有两种:1、微波炉。2、食物。所以就将微波炉和食物设计成一个接口,里面的方法都是该对象所具备的状态。

寻找状态

微波炉有打开、加热、加热是否打开、关闭4中状态。而问题主要针对是是否在加热状态。所以应该实现这两种具体类。而食物只有带皮、不带皮两种状态。问题针对也是是否有果皮。

寻找决定性因素

在微波炉和食物之中,哪个决定哪个的使用。问题假设:假如你没有食物,你还需要用到微波炉吗?假如你没有微波炉,你的食物能吃吗?从假设之中我们可以看出来,决定性因素是食物,所以在控制微波炉功能块(MicrowaveController)应该实现决定性因素(FoodState)的状态接口。

有关微波炉的代码

创建微波炉接口实现4种状态

public interface MicrowaveState {
public void caleFaction();//加热功能
public void openmicrowaveState();//打开
public void closemicrowaveState();//关闭
public void caleFactionIfOpen();//加热过程打开
}

创建属于普通状态下的微波炉

/**
* 微波炉不工作状态
* @author 林思旭
* @since 2017/3/14
*/
public class Openmicrowave implements MicrowaveState {
private Context context;
public Openmicrowave(Context context) {
this.context = context;
}
@Override
public void caleFaction() {
Toast.makeText(context,"不能进行加热,请关闭",Toast.LENGTH_SHORT).show();
}
@Override
public void openmicrowaveState() {
Toast.makeText(context,"正在打开,请稍等",Toast.LENGTH_SHORT).show();
}
@Override
public void closemicrowaveState() {
Toast.makeText(context,"正在关闭,请稍等",Toast.LENGTH_SHORT).show();
}
@Override
public void caleFactionIfOpen() {
Toast.makeText(context,"微波炉不工作,随便打开",Toast.LENGTH_SHORT).show();
}
}

创建属于加热状态下的微波炉

/**
* 微波炉具体的加热状态
* @author 林思旭
* @since 2017/3/14
*/
public class Heatmicrowave implements MicrowaveState {
private Context context;
public Heatmicrowave(Context context) {
this.context = context;
}
@Override
public void caleFaction() {
Toast.makeText(context,"加热中,请稍等",Toast.LENGTH_SHORT).show();
}
@Override
public void openmicrowaveState() {
Toast.makeText(context,"打开微波炉,准备加热",Toast.LENGTH_SHORT).show();
}
@Override
public void closemicrowaveState() {
Toast.makeText(context,"正在关闭,请稍等",Toast.LENGTH_SHORT).show();
}
@Override
public void caleFactionIfOpen() {
Toast.makeText(context,"正在加热,不能打开",Toast.LENGTH_SHORT).show();
}
}

有关食物的代码

食物状态接口

public interface FoodState {
public void exitFur();//食物带皮
public void NotExitFur();//食物不带皮
}

操控微波炉的说明书

/**
* @author 林思旭
* @since 2017/3/14
*/
public class MicrowaveController implements FoodState{
private MicrowaveState microwaveState;
private Context context;
public MicrowaveController(Context context) {
this.context = context;
}
public void setMyController(MicrowaveState microwaveState){
this.microwaveState = microwaveState;
}
/**
* 带皮食物可以打开微波炉,但是不能加热
*/
@Override
public void exitFur() {
setMyController(new Openmicrowave(context));
}
/**
* 不带皮食物可以打开微波炉、可以加热、可以关闭
*/
@Override
public void NotExitFur() {
setMyController(new Heatmicrowave(context));
}
/**
* 打开微波炉,封装好方法,透明化调用
*/
public void openMicrowave(){
microwaveState.openmicrowaveState();
}
/**
* 加热
*/
public void HeatMicrowave(){
microwaveState.caleFaction();
}
/**
* 加热过程不能打开
*/
public void openCaleFaction(){
microwaveState.caleFactionIfOpen();
}
/**
* 关闭微波炉
*/
public void closeMicrowave(){
microwaveState.closemicrowaveState();
}
}

实现了食物状态接口(FoodState),可以解决问题中带皮问题。然后再通过实例化两个不同的状态(Openmicrowave类Heatmicrowave类)下的微波炉,在对应接口方法中填入对应状态的功能,解决了加热不能打开的问题。setMyController就是用来识别食物状态对应的状态的微波炉。很好的利用接口的特性把具体对象封装起来。然后用户只需要通过MicrowaveController这个工具类对食物进行操作就可以了,完全不用知道不同状态下微波炉会具体做些什么事情。从而达到对用户的透明性。

可扩展性

具体状态的微波炉(Openmicrowave类Heatmicrowave类)中具体方法可以实现各种不同的操作,通过接口解耦从而使扩展性高。

调用代码:

public class StateActivity extends Activity {
private MicrowaveController microwaveController;
private Button btn_fur,btn_NotFur;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_state);
microwaveController = new MicrowaveController(this);
btn_fur = (Button)findViewById(R.id.btn_furHeat);
btn_NotFur = (Button)findViewById(R.id.btn_NotfurHeat);
//有果皮加热
btn_fur.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
microwaveController.exitFur();//选择水果状态
//点击微波炉上打开按钮
microwaveController.openMicrowave();
//点击微波炉上加热按钮
microwaveController.HeatMicrowave();
microwaveController.openCaleFaction();//加热时候打开
//点击微波炉上关闭按钮
microwaveController.closeMicrowave();
}
});
//没有果皮加热
btn_NotFur.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
microwaveController.NotExitFur();//选择水果状态
microwaveController.openMicrowave();
microwaveController.HeatMicrowave();
microwaveController.openCaleFaction();//加热时候打开
microwaveController.closeMicrowave();
}
});
}
}

效果图

  1. 带皮食物加热效果图
    fur_exit

  2. 不带皮食物加热效果图
    fur_noExit_one