23种设计模式总览
创建型模式
结构型模式
- 外观模式(Facade)
- 适配器模式(Adapter)
- 代理模式(Proxy)
- 组合模式(Composite)
- 享元模式(Flyweight)
- 装饰模式(Decorator)
- 桥接模式(Bridge)
行为型模式
- 中介者模式(Mediator)
- 观察者模式(Observer)
- 命令模式(Command)
- 迭代器模式(Iterator)
- 模板方法模式(Template Method)
- 策略模式(Strategy)
- 状态模式(State)
- 备忘录模式(Memento)
- 解释器模式(Interpreter)
- 职责链模式(Chain of Responsibility)
- 访问者模式(Visitor)
定义
允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
优缺点
优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点: 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
使用场景
1、行为随状态改变而改变的场景。
2、条件、分支语句的代替者。
在讲解之前先了解一下一般的状态判断和开关切换状态
"一般的状态判断"使用if..else if(条件类型多且复杂可以选择用策略模式),判断条件和state没有关系,代码如下:
if (witch == 'A') {
state = 'B';
} else if (witch == 'B') {
state = 'C';
} else if (witch == 'C') {
state = 'A';
}
"开关切换状态"就是if括号中的"witch"变成"state"
if (state == 'A') {
state = 'B';
} else if (state == 'B') {
state = 'C';
} else if (state == 'C') {
state = 'A';
}
将 state 的状态从"A"切换到"B",再切换到"C";在切换到"A",好象一个旋转开关,这种状态改变就可以使用 State 模式了。
状态模式就是把每一个if语句的状态写成一个子类,用子类来代替一个状态,这个子类包含了这个状态的行为和状态之间的转换。
实现
-
Context(环境类):环境类拥有各种不同状态的对象,作为外部使用的接口,负责调用状态类接口。
-
State(抽象状态):抽象状态既可以为抽象类,也可以直接定义成接口。主要用于定义状态抽象方法,具体实现由子类负责。
-
ConcreteState(具体状态类):具体状态类为抽象状态的实现者,不同的状态类对应这不同的状态,其内部实现也不相同。环境类中使用不同状态的对象时,能实现不同的处理逻辑
一个电视机有两种状态,关机状态和开机状态.关机状态只能开机,开机状态可以上下换台和关机.
抽象状态类
public interface State {
/**
* 开机
*/
void onState();
/**
* 关机
*/
void offState();
/**
* 上一个频道
*/
void previousState();
/**
* 下一个频道
*/
void nextState();
}
电视机类
public class TV {
//起始状态
private State state;
//关机状态
private State offState;
//开机状态
private State onState;
public TV(){
offState = new OffState(this);
onState = new OnState(this);
//起始状态为关机
state = offState;
}
//关机
public void offState(){
state.offState();
}
//下一个频道
public void next(){
state.nextState();
}
//上一个频道
public void previousState(){
state.previousState();
}
//开机
public void onState(){
state.onState();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public State getOffState() {
return offState;
}
public void setOffState(State offState) {
this.offState = offState;
}
public State getOnState() {
return onState;
}
public void setOnState(State onState) {
this.onState = onState;
}
}
关机状态类
public class OffState implements State {
TV tv;
public OffState(TV tv){
this.tv = tv;
}
@Override
public void onState() {
System.out.println("电视开机:欢迎~~~");
//状态变为开机
tv.setState(tv.getOnState());
}
@Override
public void offState() {
//无操作
}
@Override
public void previousState() {
//无操作
}
@Override
public void nextState() {
//无操作
}
}
开机状态类
public class OnState implements State{
TV tv;
public OnState(TV tv){
this.tv = tv;
}
@Override
public void onState() {
//无操作
}
@Override
public void offState() {
System.out.println("电视关机:欢迎下次观看~~~~~");
tv.setState(tv.getOnState());
}
@Override
public void previousState() {
System.out.println("进入------上一个频道");
tv.setState(tv.getOnState());
}
@Override
public void nextState() {
System.out.println("进入------下一个频道");
tv.setState(tv.getOnState());
}
}
验证
class Test {
public static void main(String[] args) {
TV tv = new TV();
//开机
tv.onState();
//下一个频道
tv.next();
//上一个频道
tv.previousState();
//关机
tv.offState();
}
}
电视开机:欢迎~~~
进入------下一个频道
进入------上一个频道
电视关机:欢迎下次观看~~~~~
策略模式和状态模式的对比
- 策略模式中,类的功能是根据当前条件主动更改;
- 状态模式中,类的功能是被动由当前状态更改;
- 策略模式中每个行为或算法之间没有关联;
- 状态模式中的状态之间有关联,并且状态本身控制着状态转移;