一起来学设计模式之备忘录模式

1,066 阅读6分钟

前言

目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

本节给大家讲一下设计模式中的备忘录模式,并结合实际业务场景给大家讲解如何使用~

本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~

备忘录模式

备忘录模式(Memento pattern)是一种行为设计模式,它允许在不破坏封装性的前提下捕获和恢复对象的内部状态。该模式为对象提供了一个能够保存状态的接口,从而可以在以后的时间点回复对象以前的状态。

在备忘录模式中,有三个角色:

  • Originator(发起人):负责创建一个备忘录 Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator 可以根据需要决定 Memento 存储自己的哪些内部状态。
  • Memento(备忘录):存储 Originator 内部状态的对象。备忘录提供了两个接口:Caretaker 只能看到备忘录的窄接口,它只能将备忘录传递给其他对象;Originator 可以看到备忘录的宽接口,允许它访问返回到先前状态所需的所有数据。
  • Caretaker(管理者):负责保存好备忘录。
public class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento state) {
        mementoList.add(state);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}


public class Memento {
    private final String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

public class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}

public class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        originator.setState("State #1");
        originator.setState("State #2");
        caretaker.add(originator.saveStateToMemento());
        originator.setState("State #3");
        caretaker.add(originator.saveStateToMemento());
        originator.setState("State #4");

        System.out.println("Current State: " + originator.getState());
        originator.getStateFromMemento(caretaker.get(0));
        System.out.println("First saved State: " + originator.getState());
        originator.getStateFromMemento(caretaker.get(1));
        System.out.println("Second saved State: " + originator.getState());
    }
}


//        Current State: State #4
//        First saved State: State #2
//        Second saved State: State #3

最佳实践

电商平台业务使用备忘录模式的场景可以是购物车功能。

在购物车功能中,用户可将需要购买的商品放入购物车中,并可以对购物车进行添加、删除、修改等操作。而当用户在进行操作时,需要保证购物车的状态能够被正确保存和还原,以免出现错误情况。这时候,备忘录模式便可以派上用场。

首先,需要定义备忘录类 CartMemento,用于保存购物车状态的类,其中包含购物车的商品列表。

public class CartMemento {
    private List<CartItem> itemList;
    public CartMemento(List<CartItem> itemList) {
        this.itemList = itemList;
    }
    public List<CartItem> getItemList() {
        return itemList;
    }
}

接下来,定义购物车类 Cart,可以对购物车进行添加、删除、修改等操作。并定义了 CartMemento 的创建和还原方法。

public class Cart {
    private List<CartItem> itemList;
    public Cart() {
        itemList = new ArrayList<>();
    }
    public void addItem(CartItem item) {
        itemList.add(item);
    }
    public void removeItem(CartItem item) {
        itemList.remove(item);
    }
    public void updateItem(CartItem item) {
        for (CartItem cartItem : itemList) {
            if(cartItem.getId() == item.getId()) {
                cartItem.setCount(item.getCount());
                break;
            }
        }
    }
    public CartMemento saveToMemento() {
        return new CartMemento(new ArrayList<>(itemList));
    }
    public void restoreFromMemento(CartMemento memento) {
        itemList = memento.getItemList();
    }
}

最后,定义 Caretaker 类作为管理者,负责保存和还原购物车的状态。其中 saveStateToMemento() 方法用于保存购物车状态,而 getStateFromMemento() 方法用于还原购物车状态。

public class Caretaker {
    private CartMemento cartMemento;
    public void saveStateToMemento(Cart cart) {
        cartMemento = cart.saveToMemento();
    }
    public void getStateFromMemento(Cart cart) {
        cart.restoreFromMemento(cartMemento);
    }
}

在购物车功能中,当用户进行操作时,可以通过 Cart 类的 saveToMemento() 方法保存购物车状态,Caretaker 类的 saveStateToMemento() 方法保存备忘录,而在需要恢复购物车状态时,可以通过 Cart 类的 restoreFromMemento() 方法将购物车状态还原为之前保存的状态,Caretaker 类的 getStateFromMemento() 方法获取备忘录并进行状态还原。

下面来测试一下:

public class MementoPatternDemo {
    public static void main(String[] args) {
        // 创建购物车和管理者
        Cart cart = new Cart();
        Caretaker caretaker = new Caretaker();

        // 向购物车添加商品
        cart.addItem(new CartItem(1, 10));
        cart.addItem(new CartItem(2, 20));
        System.out.println("添加商品到购物车: ");
        cart.getItemList().forEach(item -> System.out.println(item.getId() + ": " + item.getCount()));

        // 保存购物车状态
        caretaker.saveStateToMemento(cart);

        // 向购物车添加新的商品
        cart.addItem(new CartItem(3, 30));
        System.out.println("再次添加商品到购物车: ");
        cart.getItemList().forEach(item -> System.out.println(item.getId() + ": " + item.getCount()));

        // 恢复购物车之前的状态
        caretaker.getStateFromMemento(cart);
        System.out.println("恢复购物车状态: ");
        cart.getItemList().forEach(item -> System.out.println(item.getId() + ": " + item.getCount()));
//        添加商品到购物车:
//        1: 10
//        2: 20
//        再次添加商品到购物车:
//        1: 10
//        2: 20
//        3: 30
//        恢复购物车状态:
//        1: 10
//        2: 20
    }
}

结束语

设计模式其实并不难,大家在学习的时候一定要在理解的基础上去写代码,不要去背代码。下节给大家讲观察者模式~

本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注鼓励一下呗~

相关文章

项目源码(源码已更新 欢迎star⭐️)

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)