设计模式12-状态模式与备忘模式详解

1.12-状态模式与备忘录模式详解

1.12.1.-备忘录模式详解

时长:46min

12.1.1.备忘录模式的定义

定义:

  备忘录模式【Memento Pattern】,也称快照模式【Snapshot Pattern】,或令牌模式【Token Pattern],是指在不破坏封装的前提下,

捕获一个对象内部状态,并在对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。

  特征:"后悔药"

  属于行为型模式。

12.1.1.1.备忘录模式在生活中体现

代码版本管理中的撤销和恢复

游戏存档

12.1.1.2.备忘录模式的适用场景

1.需要保存历史快照的场景

2.希望在对象之外保存状态,且除了自己,其他类对象无法访问状态保存的具体内容。

 

12.1.2.备忘录模式的通用实现

12.1.2.1.系统类图设计
12.1.2.2.代码实现

 

12.1.3.备忘录模式的实现案例之富文本编辑

  在网页编辑中,常常会用到富文本编辑器。会提供一个草稿箱【相当于剪贴板】,支持撤销,和恢复功能。

 

  假设我们需要编写一篇博客,编写文章可能需要很长的时间,中间涉及到反复修改,撤回。。。,一般来说,我

们需要等到一篇文章彻底完成之后,才会进行发布。

  而编辑工作可能会进行多天,当再次打开上次编辑时,需要保存原来的内容。所以,先把内容保存到草稿箱中。

12.1.3.1.系统类图设计

12.1.3.2..代码实现
 1.编辑器
package com.wf.memento.demo;

/**
 * @ClassName Editor
 * @Description 编辑器,备忘录发起者
 * @Author wf
 * @Date 2020/6/19 16:26
 * @Version 1.0
 */
public class Editor {
    private String title;
    private String content;
    private String images;

    public Editor(String title, String content, String images) {
        this.title = title;
        this.content = content;
        this.images = images;
    }

    public ArticleMemento saveToMemento(){
        ArticleMemento articleMemento = new ArticleMemento(title,content,images);
        return articleMemento;
    }
    public void undoFromMemento( ArticleMemento articleMemento){
        //撤销,还原编辑器内容,为快照内容
        this.title = articleMemento.getTitle();
        this.content = articleMemento.getContent();
        this.images = articleMemento.getImages();
    }

    @Override
    public String toString() {
        return "Editor{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", images='" + images + '\'' +
                '}';
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public String getImages() {
        return images;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setImages(String images) {
        this.images = images;
    }
}

 

2.备忘录类
package com.wf.memento.demo;

/**
 * @ClassName ArticleMemento
 * @Description 文章备忘录
 * @Author wf
 * @Date 2020/6/19 16:31
 * @Version 1.0
 */
public class ArticleMemento {
    private String title;
    private String content;
    private String images;

    public ArticleMemento(String title, String content, String images) {
        this.title = title;
        this.content = content;
        this.images = images;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public String getImages() {
        return images;
    }
}

 

3.草稿箱
package com.wf.memento.demo;

import java.util.Stack;

/**
 * @ClassName DraftsBox
 * @Description 草稿箱
 * @Author wf
 * @Date 2020/6/19 16:33
 * @Version 1.0
 */
public class DraftsBox {
    /**后进先出 栈*/
    private final Stack<ArticleMemento> STACK = new Stack<ArticleMemento>();

    /**
     * 压栈,将元素压入栈顶
     * @param memento
     */
    public void addMemento(ArticleMemento memento){
        STACK.push(memento);
    }
    public ArticleMemento getMemento(){
        ArticleMemento articleMemento = STACK.pop();
        return articleMemento;
    }

}

 

4.测试类
package com.wf.memento.demo;

/**
 * @ClassName Test
 * @Description 测试类
 * @Author wf
 * @Date 2020/6/22 10:32
 * @Version 1.0
 */
public class Test {
    public static void main(String[] args) {
        DraftsBox box = new DraftsBox();
        Editor editor = new Editor("手写spring","文章节选至《。。》","xxx.png");
        ArticleMemento articleMemento = editor.saveToMemento();
        box.addMemento(articleMemento);

        System.out.println("标题:"+editor.getTitle()+
                "\n内容:"+editor.getContent()+
                "\n图片:"+editor.getImages()+
                "暂存成功");

        System.out.println("完整信息:"+editor);

        System.out.println("==========第一次修改文章==========");
        editor.setTitle("【Tom原创】,我是这样手写spring中,麻雀虽小五脏俱全");
        editor.setContent("文章节选至《。。》,tom著");

        System.out.println("===============首次完成文章修改==============");
        System.out.println("完整信息:"+editor);
        articleMemento = editor.saveToMemento();
        box.addMemento(articleMemento);
        System.out.println("===============保存到草稿箱==============");

        System.out.println("==========第二次修改文章==========");
        editor.setTitle("手写spring核心原理功能实现");
        System.out.println("完整信息:"+editor);

        System.out.println("===============第二次完成文章修改==============");
        System.out.println("==========第一次撤销回退==========");
        ArticleMemento memento = box.getMemento();
        editor.undoFromMemento(memento);
        System.out.println("完整信息:"+editor);
        System.out.println("===============第1次撤销完成==============");

        System.out.println("==========第二次撤销回退==========");
        memento = box.getMemento();
        editor.undoFromMemento(memento);
        System.out.println("完整信息:"+editor);
        System.out.println("===============第2次撤销完成==============");
    }
}

 

测试结果如下:

 

 

12.1.4.备忘录模式在源码中应用

12.1.4.1.spring-webflow中StateManageableMessageContext

需要引入依赖:

<dependency>
  <groupId>org.springframework.webflow</groupId>
  <artifactId>spring-webflow</artifactId>
  <version>2.4.5.RELEASE</version>
</dependency>

 

接口中定义:

    Serializable createMessagesMemento();

 

实现方法:

org.springframework.binding.message.DefaultMessageContext#createMessagesMemento

private Map<Object, List<Message>> sourceMessages;
public Serializable createMessagesMemento() {
        return new LinkedHashMap(this.sourceMessages);
    }

 

12.1.5.备忘录模式的使用总结

12.1.5.1.优缺点总结

优点:

1.简化发起人实体类【Originator】的职责,隔离状态存储获取。实现信息封装,客户端无须关心状态的保存细节。

2.提供状态回滚的功能。

缺点:

  1.消耗资源:如果需要存储的状态过多时,每一次保存都会消耗很多内存。

1.12.2.-状态模式详解

 时长:1h10min

学习目标:

》掌握状态模式的应用场景

》了解状态机实现订单状态流转控制的过程

》掌握状态模式与策略模式、责任链模式的区别

12.2.1.状态模式的定义

定义:

  状态模式【State Pattern】,也称为状态机模式【State Machine Pattern】,是允许对象在内部状态发生改变时

改变它的行为,对象看起来好像修改了它的子类。

  属于行为型模式。

  它的核心,是将状态与行为进行绑定,不同状态对应不同行为。

12.2.1.1.状态模式在生活中的应用

1.网购中订单状态变化

2.电梯状态的变化

12.2.1.2.状态模式的适用场景

1.行为随状态改变而改变

2.一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态。

 

12.2.2.状态模式的通用实现

12.2.2.1.类图设计

 

 

 

12.2.2.2.代码实现
1.顶层状态接口
package com.wf.state.general;

/**
 * @ClassName IState
 * @Description 顶层状态接口
 * @Author wf
 * @Date 2020/6/22 13:59
 * @Version 1.0
 */
public interface IState {
    void handle();
}

 

2.上下文对象
package com.wf.state.general;
/**
 * @ClassName Context
 * @Description 上下文对象
 * @Author wf
 * @Date 2020/6/22 14:01
 * @Version 1.0
 */
public class Context {
    private static  final IState STATE_A = new ConcreteStateA();
    private static  final IState STATE_B = new ConcreteStateB();

    //默认状态
    private IState currentState = STATE_A;
    public void setState(IState state){
        currentState = state;
    }
    public void handle(){
        this.currentState.handle();
    }

}

 

3.状态实现子类
package com.wf.state.general;

/**
 * @ClassName ConcreteStateB
 * @Description 具体状态实现子B
 * @Author wf
 * @Date 2020/6/22 14:00
 * @Version 1.0
 */
public class ConcreteStateB implements IState {
    @Override
    public void handle() {
        System.out.println("StateB do action");
    }
}
package com.wf.state.general;

/**
 * @ClassName ConcreteStateA
 * @Description 具体状态实现子类A
 * @Author wf
 * @Date 2020/6/22 14:00
 * @Version 1.0
 */
public class ConcreteStateA implements IState {
    @Override
    public void handle() {
        System.out.println("StateA do action");
    }
}

 

4.测试类
package com.wf.state.general;

/**
 * @ClassName Test
 * @Description 测试类
 * @Author wf
 * @Date 2020/6/22 14:09
 * @Version 1.0
 */
public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        context.setState(new ConcreteStateB());
        context.handle();
    }
}

 

测试结果:

12.2.3.状态模式的使用案例之访问权限系统

  比如:当我们访问一个社区时,如果未登录【游客】,当我们看到一篇好的文章,想要进行收藏。是不存在的,是无法看到的。

只有当登录后,才允许访问。

  这里的是否登录【是两种不同的状态】,对应了不同的行为。

12.2.3.1.类图设计

 

 

12.2.3.2.代码实现
1.顶层用户状态抽象类
package com.wf.state.demo.gper;

/**
 * @ClassName UserState
 * @Description 用户状态
 * @Author wf
 * @Date 2020/6/22 14:24
 * @Version 1.0
 */
public abstract class UserState {
    //抽象类引入context
    protected AppContext context;

    public void setContext(AppContext context) {
        this.context = context;
    }

    //收藏功能
    public abstract void favorite();
    //评论
    public abstract void comment(String comment);

}

 

2.上下文对象
package com.wf.state.demo.gper;

/**
 * @ClassName AppContext
 * @Description 上下文
 * @Author wf
 * @Date 2020/6/22 14:26
 * @Version 1.0
 */
public class AppContext {
    public static final UserState STATE_LOGIN = new LoginState();
    public static final UserState STATE_UNLOGIN = new UnLoginState();
    private UserState currentState = STATE_UNLOGIN;
    {
        STATE_LOGIN.setContext(this);
        STATE_UNLOGIN.setContext(this);
    }
    public void setState(UserState currentState){
        this.currentState = currentState;
    }
    public UserState getState(){
        return currentState;
    }

    public void favorite(){
        this.currentState.favorite();
    }

    public void comment(String comment){
        this.currentState.comment(comment);
    }
}

 

3.用户状态实现子类
package com.wf.state.demo.gper;

/**
 * @ClassName UnLoginState
 * @Description 未登录状态
 * @Author wf
 * @Date 2020/6/22 14:27
 * @Version 1.0
 */
public class UnLoginState extends UserState {
    @Override
    public void favorite() {
        //要想收藏,先进行登录
        this.switchToLogin();
        //调用登录后的功能
        this.context.getState().favorite();
    }

    @Override
    public void comment(String comment) {
        this.switchToLogin();
        this.context.getState().comment(comment);
    }
    private void switchToLogin(){
        System.out.println("跳转到登录页,进行登录");
        //登录完成后,切换为登录状态
        this.context.setState(this.context.STATE_LOGIN);
    }
}
package com.wf.state.demo.gper;

/**
 * @ClassName UnLoginState
 * @Description 未登录状态
 * @Author wf
 * @Date 2020/6/22 14:27
 * @Version 1.0
 */
public class UnLoginState extends UserState {
    @Override
    public void favorite() {
        //要想收藏,先进行登录
        this.switchToLogin();
        //调用登录后的功能
        this.context.getState().favorite();
    }

    @Override
    public void comment(String comment) {
        this.switchToLogin();
        this.context.getState().comment(comment);
    }
    private void switchToLogin(){
        System.out.println("跳转到登录页,进行登录");
        //登录完成后,切换为登录状态
        this.context.setState(this.context.STATE_LOGIN);
    }
}

 

4.测试类
package com.wf.state.demo.gper;

/**
 * @ClassName Test
 * @Description 测试类
 * @Author wf
 * @Date 2020/6/22 14:39
 * @Version 1.0
 */
public class Test {
    public static void main(String[] args) {
        AppContext context = new AppContext();
        //默认为未登录状态
        context.favorite();

        context.comment("你好,你评论得perfect");
    }
}

 

测试结果:

 

 

12.2.4.状态模式的使用案例之spring状态机使用

  状态机模式,是在context的基础上,进行的一种优化。spring-statemachine模块有提供相关功能。

需求:

  基于spring-statemachine实现状态机模式应用。这里以订单状态流程处理为例:

依赖包:

<!--状态机-->
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>

 

12.2.4.1.类图设计

 

 

12.2.4.2.代码实现
1.定义订单实体类
package com.wf.state.demo.order;

/**
 * @ClassName Order
 * @Description 订单,业务bean
 * @Author wf
 * @Date 2020/6/22 15:14
 * @Version 1.0
 */
public class Order {
    private Integer id;
    private OrderStatus status;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public OrderStatus getStatus() {
        return status;
    }

    public void setStatus(OrderStatus status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", status=" + status +
                '}';
    }
}

 

2.订单状态枚举常量
package com.wf.state.demo.order;

/**
 * @ClassName OrderStatus
 * @Description 订单状态枚举
 * @Author wf
 * @Date 2020/6/22 15:17
 * @Version 1.0
 */
public enum OrderStatus {
    //待支付,待发货,待收货,订单结束
    WAIT_PAYMENT,WAIT_DELIVER,WAIT_RECEIVE,FINISH;
}

 

3.订单变更行为状态
package com.wf.state.demo.order;

/**
 * @ClassName OrderStatusChangeEvent
 * @Description 订单状态变更行为状态
 * @Author wf
 * @Date 2020/6/22 15:21
 * @Version 1.0
 */
public enum OrderStatusChangeEvent {
    //支付,发货,确认收货
    PAYED,DELIVER,RECEIVED;
}

 

4.定义订单状态机配置类
package com.wf.state.demo.order;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;

import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;


import java.util.EnumSet;

/**
 * @ClassName OrderStatusMachineConfig
 * @Description 订单状态机配置类
 * @Author wf
 * @Date 2020/6/22 15:24
 * @Version 1.0
 */
@Configuration
@EnableStateMachine(name="orderStateMachine")
public class OrderStatusMachineConfig extends StateMachineConfigurerAdapter<OrderStatus,OrderStatusChangeEvent> {
    /**
     * 配置状态,初始化状态为OrderStatus.WAIT_PAYMENT【待支付】
     * @param states
     * @throws Exception
     */
    public void configure(StateMachineStateConfigurer<OrderStatus,OrderStatusChangeEvent> states) throws Exception {
        states.withStates()
                .initial(OrderStatus.WAIT_PAYMENT)
                .states(EnumSet.allOf(OrderStatus.class));
    }

    /**
     * 配置状态转换事件关系
     * @param transitions
     * @throws Exception
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {
        transitions
                .withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED)
                .and()
                .withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVER)
                .and()
                .withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderStatusChangeEvent.RECEIVED);
    }

    /**
     * 持久化配置
     * 实际使用中,可以结合redis等进行缓存
     * @return
     */
    @Bean
    public DefaultStateMachinePersister persister(){
        return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() {
            @Override
            public void write(StateMachineContext<Object, Object> stateMachineContext, Order order) throws Exception {
                //持久化操作略
            }

            @Override
            public StateMachineContext<Object, Object> read(Order order) throws Exception {
                //此处直接获取order中订单状态,其实并没有进行持久化操作
                return new DefaultStateMachineContext<>(order.getStatus(),null,null,null);
            }
        });

    }
}
 5.定义listener监听器
package com.wf.state.demo.order;

/**
 * @ClassName OrderStatusListenerImpl
 * @Description 监听器实现
 * @Author wf
 * @Date 2020/6/22 15:48
 * @Version 1.0
 */

import org.springframework.messaging.Message;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;
import org.springframework.stereotype.Component;

@Component("orderStateListener")
@WithStateMachine(name="orderStateMachine")
public class OrderStatusListenerImpl  {
    @OnTransition(source ="WAIT_PAYMENT", target = "WAIT_DELIVER")
    public boolean payTransaction(Message<OrderStatusChangeEvent> message){
        Order order = (Order) message.getHeaders().get("order");
        order.setStatus(OrderStatus.WAIT_DELIVER);
        System.out.println("支付,状态机反馈信息:"+message.getHeaders().toString());
        return true;
    }
    @OnTransition(source ="WAIT_DELIVER", target = "WAIT_RECEIVE")
    public boolean deliverTransaction(Message<OrderStatusChangeEvent> message){
        Order order = (Order) message.getHeaders().get("order");
        order.setStatus(OrderStatus.WAIT_RECEIVE);
        System.out.println("发货,状态机反馈信息:"+message.getHeaders().toString());
        return true;
    }
    @OnTransition(source ="WAIT_RECEIVE", target = "FINISH")
    public boolean receiveTransaction(Message<OrderStatusChangeEvent> message){
        Order order = (Order) message.getHeaders().get("order");
        order.setStatus(OrderStatus.FINISH);
        System.out.println("收货,状态机反馈信息:"+message.getHeaders().toString());
        return true;
    }

}

 

6. 订单服务接口及实现
package com.wf.state.demo.order;

import java.util.Map;

/**
 * @ClassName IOrderService
 * @Description 订单服务接口
 * @Author wf
 * @Date 2020/6/22 16:20
 * @Version 1.0
 */
public interface IOrderService {
    Order create();

    Order pay(int id);

    Order deliver(int id);

    Order receive(int id);

    Map<Integer,Order> getOrders();
}
package com.wf.state.demo.order;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName OrderServiceImpl
 * @Description 订单服务
 * @Author wf
 * @Date 2020/6/22 15:57
 * @Version 1.0
 */
@Service("orderService")
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;

    @Autowired
    private StateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister;
    private int id = 1;
    private Map<Integer,Order> orders = new HashMap<Integer, Order>();

    public Order create(){
        Order order = new Order();
        order.setStatus(OrderStatus.WAIT_PAYMENT);
        order.setId(id++);
        orders.put(order.getId(),order);
        return order;
    }

    public Order pay(int id){
        Order order = orders.get(id);
        System.out.println("线程名称:"+Thread.currentThread().getName() + "尝试支付,订单号:"+id);
        Message message = MessageBuilder.withPayload(OrderStatusChangeEvent.PAYED).setHeader("order",order).build();
        if(!sendEvent(message, order)){
            System.out.println("线程名称:"+Thread.currentThread().getName() + "支付失败,状态异常,订单号:"+id);
        }
        return orders.get(id);
    }

    public Order deliver(int id){
        Order order = orders.get(id);
        System.out.println("线程名称:"+Thread.currentThread().getName() + "开始发货,订单号:"+id);
        Message message = MessageBuilder.withPayload(OrderStatusChangeEvent.DELIVER).setHeader("order",order).build();
        if(!sendEvent(message, order)){
            System.out.println("线程名称:"+Thread.currentThread().getName() + "发货失败,状态异常,订单号:"+id);
        }
        return orders.get(id);
    }

    public Order receive(int id){
        Order order = orders.get(id);
        System.out.println("线程名称:"+Thread.currentThread().getName() + "开始收货,订单号:"+id);
        Message message = MessageBuilder.withPayload(OrderStatusChangeEvent.RECEIVED).setHeader("order",order).build();
        if(!sendEvent(message, order)){
            System.out.println("线程名称:"+Thread.currentThread().getName() + "收货失败,状态异常,订单号:"+id);
        }
        return orders.get(id);
    }

    public Map<Integer, Order> getOrders(){
        return orders;
    }

    /**
     * 发送订单状态转换事件
     * @param message
     * @param order
     * @return
     */
    private synchronized boolean sendEvent(Message message, Order order) {
        boolean result = false;
        try{
            orderStateMachine.start();
            //尝试恢复状态机状态
            persister.restore(orderStateMachine, order);
            //添加线程延时,用于线程安全测试
            Thread.sleep(1000);
            result = orderStateMachine.sendEvent(message);
            //持久化状态机状态
            persister.persist(orderStateMachine, order);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            orderStateMachine.stop();
        }
        return result;
    }
}

 

7.测试类
package com.wf.state.demo.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @ClassName Test
 * @Description 测试类
 * @Author wf
 * @Date 2020/6/22 16:21
 * @Version 1.0
 */
@SpringBootApplication
public class Test {
    public static void main(String[] args) {
        Thread.currentThread().setName("主线程");
         ConfigurableApplicationContext context = SpringApplication.run(Test.class,args);

        IOrderService orderService = (IOrderService) context.getBean("orderService");
        orderService.create();
        orderService.create();

        orderService.pay(1);

        new Thread("客户线程"){
            @Override
            public void run() {
                orderService.deliver(1);
                orderService.receive(1);

            }
        }.start();

        orderService.pay(2);
        orderService.deliver(2);
        orderService.receive(2);
        System.out.println("订单全部状态:"+orderService.getOrders());
    }
}

 

测试结果:

 

 12.1.5.状态模式在源码中的应用

  状态模式,在源码中很少用到。

12.1.5.1.在jsf中应用

依赖包:

   <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-api</artifactId>
      <version>1.2</version>
    </dependency>

 

jsf是一个前端框架。

Lifecycle是相当于状态顶层抽象接口,源码如下所示:

package javax.faces.lifecycle;

import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseListener;

public abstract class Lifecycle {
    public Lifecycle() {
    }

    public abstract void addPhaseListener(PhaseListener var1);

    public abstract void execute(FacesContext var1) throws FacesException;//关联上下文对象

    public abstract PhaseListener[] getPhaseListeners();

    public abstract void removePhaseListener(PhaseListener var1);

    public abstract void render(FacesContext var1) throws FacesException;
}

 

jsf是一个前端框架,它关注一个请求从页面打开,点击触发请求,到返回结果的一个过程。

PhaseId类定义多个状态常量。如下所示:

 

  

12.1.6.状态模式使用总结

12.1.6.1.状态模式与其他模式的区别
1.状态模式与责任链模式

状态模式:

  强调是内部状态的一个变化,通常是种流程化的演变。

  状态模式各个状态对象知道自己下一个要进入的状态对象。

责任链模式:

  强调外部节点对象间的改变

  而责任链模式并不清楚其下一个节点处理对象,因为链式组装由客户端负责。

 

状态模式和责任链模式都能消除if分支过多的问题。但某些情况下,状态模式中的状态可以理解为责任

2.状态模式与策略模式

状态模式和策略模式的UML类图架构几乎完全一样, 但他们的应用场景是不一样的。

策略模式多种算法行为择其一都能满足,彼此之间是独立的,用户可自行更换策略算法

而状态模式各个状态间是存在相互关系的,彼此之间在一定条件下存在自动切换状态效果,且用户无法指定状态,只能设置初始状态。

12.1.6.2.状态模式的优缺点总结

优点:

1.结构清晰:将状态独立为类, 消除了冗余的if...else或switch...case语句, 使代码更加简洁,提高系统可维护性;

2.将状态转换显式化:通常的对象内部都是使用数值类型来定义状态,状态的切换是通过赋值进行表现,不够直观;

而使用状态类,在切换状态时,是以不同的子类进行表示,转换目的更加明确;

3.状态类职责明确且具备扩展性

缺点:

1.类膨胀:如果一个事物具备很多状态,则会造成状态类太多

2.状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱;

3.状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,

否则无法切换到新增状态,而且修改某个状态类的行为也需要修改源代码。

posted @ 2020-06-19 17:03  我爱钻研  阅读(359)  评论(1编辑  收藏  举报