1、状态模式

简要说明

允许一个对象在其内部改变时改变它的行为


(资料图片仅供参考)

速记关键字

状态变成类

类图如下

状态模式主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。比如订单从待付款到待收货的咋黄台发生变化,执行的逻辑是不一样的。

所以我们将状态抽象为一个接口或者抽象类,对不同状态进行封装成单独的实体,用于实现各种状态处理的逻辑。

再设计一个上下文类,它组合了状态接口,用于发送请求。针对不同的状态提供不同的处理方法即可。

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 List persons = 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、小结

其实我们可以看出,状态模式和策略模式很类似,简直就是亲兄弟一样。而访问者模式其实和观察者模式也很类似。所以我们的设计模式设计到最后,可能就会存在一种模式里有另一种模式的影子。所以我们要搞清楚它们之间的区别。

推荐内容