策略模式
策略模式为同一个行为定义了不同策略,为每种策略实现了不同方法。用户使用时系统根据不同的策略自动切换不同的方法实现策略的改变。同一策略下的不同方法是对同一功能的不同实现,因此在使用时可相互替换而不影响用户的使用。
策略模式的实现是在接口中定义不同的策略,在实现类中完成了对不同策略下具体行为的实现,并将用户的策略状态存储在上下文中来完成策略的存储和状态的改变。
下面设计的场景是,我们需要画一个图形,可选的策略就是用红色笔来画,还是绿色笔来画,或者蓝色笔来画。
首先,先定义一个策略接口:
public interface Strategy {
public void draw(int radius, int x, int y);
}
然后我们定义具体的几个策略:
public class RedPen implements Strategy {
@Override
public void draw(int radius, int x, int y) {
System.out.println("用红色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
}
}
public class GreenPen implements Strategy {
@Override
public void draw(int radius, int x, int y) {
System.out.println("用绿色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
}
}
public class BluePen implements Strategy {
@Override
public void draw(int radius, int x, int y) {
System.out.println("用蓝色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
}
}
使用策略的类:
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeDraw(int radius, int x, int y){
return strategy.draw(radius, x, y);
}
}
客户端演示:
public static void main(String[] args) {
Context context = new Context(new BluePen()); // 使用绿色笔来画
context.executeDraw(10, 0, 0);
}
在使用策略模式时,需要先定义一个Context,定义不同的策略实现并注入Context实现不同策略的切换,放到一张图上,让大家看得清晰些:

状态模式 State
状态模式指给对象定义不同的状态,并为不同的状态定义不同的行为,在对象的状态发生变换时自动切换状态的行为。状态模式是一种对象行为型模式,它将对象的不同行为封装到不同的状态中,遵循单一职责原则。
具体角色如下:
(1)环境: 也叫做上下文,用于维护对象当前的状态,并在对象状态发生变化时触发对象行为的变化
(2)抽象状态:定义接口,用于定义对象中不同状态对应行为
(3)具体状态:抽象状态的实现类
state类,定义各个状态需要实现的行为:
public abstract class State {
public abstract void handle(Context context);
}
具体状态类,定义各个状态,并定义内部状态转移规则A-B-C,当然也可以使用外部状态,有context类直接设置,这样一来有点像策略模式,本人觉得内部状态才是真正的状态模式,内部状态需要具体状态类可以访问context对象,可以使用传入或者初始化持有的方式:
public class ConcreteStateA extends State {
@Override
public void handle(Context context) {
System.out.println(this.getClass().getName());
// 转移状态
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB extends State {
@Override
public void handle(Context context) {
System.out.println(this.getClass().getName());
// 转移状态
context.setState(new ConcreteStateC());
}
}
public class ConcreteStateC extends State {
@Override
public void handle(Context context) {
System.out.println(this.getClass().getName());
// 转移状态
context.setState(new ConcreteStateA());
}
}
(4)定义Context存储状态和执行不同状态下行为
public class Context {
private State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void handle(){
state.handle(this);
}
}
(5)使用状态模式
public static void main(String[] args) {
Context context = new Context();
context.setState(new ConcreteStateA());//设置起始状态
context.handle();
context.handle();
context.handle();
context.handle();
}
输出,可以清晰看出内部状态之间的流转,而使用端可以不了解状态:
strategy.ConcreteStateA
strategy.ConcreteStateB
strategy.ConcreteStateC
strategy.ConcreteStateA
使用状态模式时,只需定义一个上下文Context,并设置Context中的状态,然后调用行为方法即可。
策略模式和状态模式对比
不同点
策略模式
重行为,轻数据,抽象行为,所有接口抽象都可以认为是策略模式的变种,要求策略之间平等,可以相互替换,使用端必须了解不同策略之间的区别,才可以选择正确的行为;策略模式多用于算法替换
状态模式
重数据,轻行为,各个状态之间可以相互流转,各个状态之间不平等,不能相互替换,使用端不需要了解对象各个状态可以正确使用对象(此处有些线程各个状态间切换的感觉);状态模式可以实现状态机
相同点:
都是对类的某一点进行抽象(策略模式主要是方法,状态模式主要是数据),类图相似,都容易造成类泛滥,个人觉得外部状态的状态模式其实就是策略模式,策略模式的范围应该比状态模式要大

679

被折叠的 条评论
为什么被折叠?



