简要说明
允许一个对象在其内部改变时改变它的行为
(资料图片仅供参考)
速记关键字
状态变成类
类图如下
状态模式主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。比如订单从待付款到待收货的咋黄台发生变化,执行的逻辑是不一样的。
所以我们将状态抽象为一个接口或者抽象类,对不同状态进行封装成单独的实体,用于实现各种状态处理的逻辑。
再设计一个上下文类,它组合了状态接口,用于发送请求。针对不同的状态提供不同的处理方法即可。
Java代码实现
/** * 状态接口 提供处理状态的方法 */public interface IState { // 处理状态,交给实现类实现 void handleState();}/** * 未付款状态 */public class UnpaidState implements IState{ @Override public void handleState() { System.out.println("下单成功,订单状态为待付款"); }}/** * 已付款状态 */public class PaidState implements IState{ @Override public void handleState() { System.out.println("支付成功,订单状态为已付款"); }}/** * 已取消状态 */public class CancelState implements IState{ @Override public void handleState() { System.out.println("订单取消支付,订单状态为已取消"); }}/** * 订单状态上下文类 */public class Context { // 组合订单状态 private final IState state; public Context(IState state) { this.state = state; } // 提供处理订单方法 public void handleOrderByState(){ state.handleState(); }}/** * 测试类 */public class Client { public static void main(String[] args) { // 创建上下文并创建未支付状态 Context context = new Context(new UnpaidState()); context.handleOrderByState(); // 创建上下文并创建已支付状态 Context context2 = new Context(new PaidState()); context2.handleOrderByState(); }}
结果输出
其实我们可以看出来,状态模式和策略模式非常像,都有一个Context类,都有一个接口或抽象类被Context组合。而后抽象类或接口有自己的不同实现。
它们确实很像,但是它们确实有区别,因为状态模式围绕着状态的变化,它的子类之间的状态是可以进行转换的,比如订单状态由未付款变为已付款。但是策略模式则不会,只会二者取其一,进行一种策略操作。
2、访问者模式简要说明
表示一个作用域某对象结构中的个元素的操作,使得在不改变各元素的前提下定义作用域这些元素的新操作。
速记关键字
数据与操作分离
类图如下
角色说明
Visitor(抽象访问者):为每种具体的被访问者(ConcreteElement)声明一个访问操作ConcreteVisitor(具体访问者):实现对被访问者(ConcreteElement)的具体访问操作,所以需要组合多个元素,也就是组合一组元素集合Element(抽象被访问者):通常有一个Accept方法,用来接收/引用一个抽象访问者对象(基本原理)ConcreteElement(具体被访问者对象):实现Accept抽象方法,通过传入的具体访问者参数、调用具体访问者对该对象的访问操作方法实现访问逻辑Clent、ObjectStructure(客户端访问过程测试环境):该过程中,被访问者通常为一个集合对象,通过对集合的遍历完成访问者对每一个被访问元素的访问操作;Java代码实现
/** * 定义被访问接口 */public interface Person { // 提供一个方法,让访问者可以访问 void accept(Action action);}/** * 访问者,这里提供了多个访问方法,从而获取多个不同的访问结果,它们的参数分别对应具体的被访问元素 */public interface Action { // 得到男性 的测评 void getManResult(Man man); // 得到女的 测评 void getWomanResult(Woman woman);}/** * 被访问者元素男人实现,传入自己给访问者访问 */public class Man implements Person{ @Override public void accept(Action action) { action.getManResult(this); }}/** * 被访问者元素女人实现,传入自己给访问者访问 */public class Woman implements Person{ @Override public void accept(Action action) { action.getWomanResult(this); }}/** * 访问者实现类 对不同的被访问元素做不同的访问 */class Success implements Action { @Override public void getManResult(Man man) { System.out.println("男人给的评价: 歌手很表演很nice"); } @Override public void getWomanResult(Woman woman) { System.out.println("女人给的评价: 歌手很表演很nice"); }}class Normal implements Action { @Override public void getManResult(Man man) { System.out.println("男人给的评价是: 歌手很表演比较普通"); } @Override public void getWomanResult(Woman woman) { System.out.println("女人给的评价是: 歌手很表演比较普通"); }}public class Fail implements Action { @Override public void getManResult(Man man) { System.out.println("男人给的评价: 歌手很表演有点糟糕"); } @Override public void getWomanResult(Woman woman) { System.out.println("女人给的评价: 歌手很表演有点糟糕"); }}/** * 数据结构,管理很多人(Man , Woman) */class ObjectStructure { //维护了一个集合 private Listpersons = new LinkedList<>(); //添加 public void add(Person p) { persons.add(p); } //删除 public void delete(Person p) { persons.remove(p); } // 显示测评情况(便利) public void show(Action action) { for (Person p : persons) { p.accept(action); } }}/** * 测试类 */public class Client { public static void main(String[] args) { // 使用数据结构来创建 ObjectStructure os = new ObjectStructure(); // 添加我们我们的访问者 os.add(new Man()); os.add(new Woman()); // 创建成功的被访问者 Success success = new Success(); // 通过数据结果遍历访问者,然后进行访问成功的数据 os.show(success); System.out.println("========================"); // 创建失败的被访问者 Fail fail = new Fail(); // 通过数据结果遍历访问者,然后进行访问失败的数据 os.show(fail); System.out.println("========================"); // 创建中肯的的被访问者 Normal normal = new Normal(); os.show(normal); }}
其实访问者模式和观察者模式的思想也非常类似,代码实现也很类似。都会提供一个管理被访问者/观察者集合,提供新增和删除方法,并且提供一个遍历集合的方法,并通知所有元素或者指定元素的方法。
它们只是应用场景不一样,其实类图都很类似。
结果输出
3、小结其实我们可以看出,状态模式和策略模式很类似,简直就是亲兄弟一样。而访问者模式其实和观察者模式也很类似。所以我们的设计模式设计到最后,可能就会存在一种模式里有另一种模式的影子。所以我们要搞清楚它们之间的区别。