天天看点

(二)面向可维护性的Java设计模式

目录

        • 目录
        • 2、面向可维护性的设计模式
          • 2.1、创建型模式
            • 2.1.1、factory(工厂模式)
            • 2.1.2、abstract factory(抽象工厂模式)
            • 2.1.3、builder(建造者模式)
            • 2.2.2、proxy(代理模式)
            • 2.2.3、composite(组合模式)
          • 2.3、行为类模式
            • 2.3.1、observer(观察者模式)
            • 2.3.2、visitor(访问者模式)
          • 2.4、基于状态的模式
            • 2.3.4、state(状态模式)
            • 2.3.5、memento(备忘录模式)

2、面向可维护性的设计模式

2.1、创建型模式

2.1.1、factory(工厂模式)

虚拟构造器。

当client不知道要创建哪个具体类的实例,或者不想在client代码中指明要具体

创建的实例时,用工厂方法。

定义一个用于创建对象的接口,让其子类来决定实例化哪一个类,从而使一个

类的实例化延迟到其子类。

常规情况下,客户端直接创造具体对象

使用工厂模式下

体现了OCP原则—对扩展的开放,对修改已有代码的封闭。

继承树

(二)面向可维护性的Java设计模式

举例

/* 父接口,轨迹 */
public interface Trace {
    public void setDebug( boolean debug );
    public void debug( String message );
    public void error( String message );
}
/* 子类1,文件轨迹 */
public class FileTrace implements Trace {
    private boolean debug;
    public FileTrace(){...}
    public void setDebug( boolean debug ) {...}
    public void debug( String message ) {...}
    public void error( String message ) {...}
}
/* 子类2,系统轨迹 */
public class  SystemTrace implements Trace {
    private boolean debug;
    public SystemTrace(){...}
    public void setDebug( boolean debug ) {...}
    public void debug( String message ) {...}
    public void error( String message ) {...}
}
/* 工厂接口,有多种实现形式,也可以有其他操作 */
interface TraceFactory {
    public Trace getTrace();
    public Trace getTrace(String type);
    void otherOperation(){};
}
/* 工厂子类实现1 */
public class Factory1 implements TraceFactory {
    public Trace getTrace() {
        return new SystemTrace();
    }
}
/* 工厂子类实现2,根据类型决定创建哪个具体产品  */
public class Factory2 implements TraceFactory {
    public getTrace(String type) {
        if(type.equals(“file”)
            return new FileTrace();
        else if (type.equals(“system”)
            return new SystemTrace();
}
/* 客户端 */
    Trace log1 = new Factory1().getTrace();
    log1.setDebug(true);
    log1.debug( "entering log" );
    /* 选择类型 */
    Trace log2 = new Factory2().getTrace("system");
    log2.setDebug(false);
    log2.debug("...");
           

工厂模式,有两个接口,第一个接口,是产品接口,然后有多个实现子类,实现了多种产品;第二个接口是工厂接口,可以有多个实现子类(每个子类只返回一种特定产品),或实现一个子类(根据输入选择,返回一种产品)。

还有一种静态工厂方法(工厂方法前加

static关键

字),既可以在ADT内部实现,也可以构造单独的工厂类。

创建对象时,不同使用

new

关键字,

2.1.2、abstract factory(抽象工厂模式)

抽象工厂模式:提供接口以创建一组相关/相互依赖的对象,但不需要指明其具体类。

继承树(有点乱)

(二)面向可维护性的Java设计模式

这个倒是好点

(二)面向可维护性的Java设计模式

创建的不是一个完整产品,而是“产品族”(遵循固定搭配规则的多类产品的实例),得到的结果是:多个不同产品的object,各产品创建过程对client可见,但“搭配”不能改变。

本质上,Abstract Factory(使用组合、委托)是把多类产品的factory method(使用继承、子类型)组合在一起

举例

/* 抽象产品接口-窗口 */
public interface Window{
    ...
}
/* 窗口实现1 */
public class WindowOne implements Window{
    ...
}
/* 窗口实现2 */
public class WindowTwo implements Window{
    ...
}
/* 抽象产品接口-滑块 */
public interface Scrollbar{
    ...
}
/* 滑块实现1 */
public class ScrollbarOne implements Scrollbar{
    ...
}
/* 滑块实现2 */
public class ScrollbarTwo implements Scrollbar{
    ...
}
/* 抽象工厂接口 */
public interface AbstractWidgetFactory{
    public Window createWindow();
    public Scrollbar createScrollbar();
}
/* 工厂实现类1,WindowOne + ScrollbarOne */
public class WidgetFactory1 extends AbstractWidgetFactory{
    public Window createWindow(){
        return new WindowOne();
    }
    public Scrollbar createScrollbar(){
        return new ScrollbarOne();
    }
}
/* 工厂实现类2,WindowTwo + ScrollbarTwo */
public class WidgetFactory2 extends AbstractWidgetFactory{
    public Window createWindow(){
        return new WindowTwo();
    }
    public Scrollbar createScrollbar(){
        return new ScrollbarTwo();
    }
}
/* 客户端 */
public class GUIBuilder{
    public void buildWindow(AbstractWidgetFactory widgetFactory){
        /* 创建WindowOne + ScrollbarOne */
        Window window = widgetFactory1.createWindow();
        Scrollbar scrollbar = widgetFactory1.createScrollbar();
    }
}
           

可以很明显的看到,抽象工厂就多个工厂模式的组合,其组合是固定的。总共有三个接口,包括两个产品接口Window和Scrollbar,以及抽象工厂接口,两个产品接口分别两个实现类,抽象工厂有两个子类,分别是WindowOne+Scrollbar和WindowTwo+ScrollbarTwo。

需要注意的是,抽象工厂返回的是产品族,搭配是固定的,而且是分别返回(上述有一个返回Window的方法,和一个返回Scrollbar的方法)。

2.1.3、builder(建造者模式)

创建复杂对象,包含多个组成部分。

继承树

(二)面向可维护性的Java设计模式

举例:

/* 产品,Pizza */
class Pizza {
    /* 三个part以三个属性体现 */
    private String dough = "";
    private String sauce = "";
    private String topping = "";
    public void setDough(String dough) {
        this.dough = dough;
    }
    public void setSauce(String sauce) {
        this.sauce = sauce;
    }
    public void setTopping(String topping) {
        this.topping = topping;
    }
}
/* Builder抽象类 */
abstract class PizzaBuilder {
    protected Pizza pizza;
    public Pizza getPizza() {
        return pizza;
    }
    public void createNewPizzaProduct() {
        pizza = new Pizza();
    }
    /* 三个抽象方法,分别创建三个part */
    public abstract void buildDough();
    public abstract void buildSauce();
    public abstract void buildTopping();
}
/* Builder1,子类,重写三个方法,分别构建三个parts */
class SpicyPizzaBuilder extends PizzaBuilder {
    public void buildDough() {
        pizza.setDough("pan baked");
    }
    public void buildSauce() {
        pizza.setSauce("hot");
    }
    public void buildTopping() {
        pizza.setTopping("pepperoni+salami");
    }
}
/* Builder2,子类,分别构建三个parts */
class HawaiianPizzaBuilder extends PizzaBuilder {
    public void buildDough() {
        pizza.setDough("cross");
    }
    public void buildSauce() {
        pizza.setSauce("mild");
    }
    public void buildTopping() {
        pizza.setTopping("ham+pineapple");
    }
}
/*  Waiter,定义delegation的对象(某个Builder子类),
* 并具体构建各部分,以及返回最终结果
*/
class Waiter {
    private PizzaBuilder pizzaBuilder;
    /* 定义delegation对象 */
    public void setPizzaBuilder(PizzaBuilder pb) {
        pizzaBuilder = pb;
    }
    public Pizza getPizza() {
        return pizzaBuilder.getPizza();
    }
    /* 构建各个部分,调用选择的Builder的方法 */
    public void constructPizza() {
        pizzaBuilder.createNewPizzaProduct();
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildTopping();
    }
}
/* 客户端 */
public class PizzaBuilderDemo {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        /* 分别创建两个建造者 */
        PizzaBuilder hawaiianPizzabuilder = new HawaiianPizzaBuilder();
        PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
        /* 选择建造者 */
        waiter.setPizzaBuilder( hawaiianPizzabuilder );
        /* 进行构建,且构建细节完全隐藏 */
        waiter.constructPizza();
        /* 返回构建对象 */
        Pizza pizza = waiter.getPizza();
    }
}
           

分析上述代码,产品为Pizza类,有三个组件,三个方法分别为组件赋值;Builder抽象类,有一个产品实例,以及创建和返回产品的方法,三个构造组件的抽象方法;Builder

1和Builder2继承Builder抽象类,具体实现构建三个组件以及为Pizza属性赋值的方法;Director(即Waiter),具体构建产品,有一个Builder对象,以及设置Builder类型和返回Pizza(Builder中的)的方法,和一个构建函数(调用Builder的三个构建方法)。客户端,只用创建一个Waiter对象,以及选择一种Builder方式,将Builder方式传入Waiter对象,再调用Waiter的构建方法,最后得到Waiter返回的Pizza对象即可。

可以发现,Builder和之前的抽象工厂和模板有相似性,但有一定的差别:

抽象工厂 vs 建造者 模板模式 vs 建造者
抽象工厂 建造者 模板模式 建造者
返回的时候产品族,具有固定的搭配规则,产品构建过程对client可见,客户端可以看到是如何组装的,但搭配不能变 创建的是一个完整的产品,构建过程对client不可见,其实,抽象工厂中client的构建过程是在Director(组织者)中完成的,最终直接给客户端返回一个完整的产品 目标是为了复用算法的公共结构(次序)(使用super直接只有模板中的代码过程) 创建复杂的对象,灵活扩展

> ##### 2.2、结构型模式 ###### 2.2.1、bridge(桥接模式) Bridge是OOP最基本的structural pattern,通过delegation+inheritance建立两个具体类之间的关系(DIP依赖转置,抽象依赖于抽象) 继承树 ![这里写图片描述](https://img-blog.csdn.net/20180622185446348?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2OTYyNTY5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 举例

/* 桥接口 */
public interface DrawAPI {
    public void drawCircle(int radius, int x, int y);
}
/* 桥子类1 */
public class DrawRedCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println(“Color: red " + radius + x + y);
    }
}
/* 桥子类2 */
public class DrawGreenCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println(“Color: green " + radius + x + y);
    }
}
/* 形状抽象类 */
public abstract class Shape {
    protected DrawAPI drawAPI;
    protected Shape(DrawAPI drawAPI){
        this.drawAPI = drawAPI;
    }
    public abstract void draw();
}
/* 具体形状子类-圆形 */
public class Circle extends Shape {
    private int x, y, radius;
    /* 构造方法比父类多了几个参数,但相同的参数可以直接使用super赋值 */
    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }
    /* 使用选择的桥画圆 */
    public void draw() {
        drawAPI.drawCircle(radius,x,y);
    }
}
/* 客户端 */
public class BridgePatternDemo {
    public static void main(String[] args) {
        /* 创建两个圆,分别传入桥1-红色和桥2-绿色 */
        Shape redCircle = new Circle(,, , new DrawRedCircle());
        Shape greenCircle = new Circle(,, , new DrawGreenCircle());
        /* 调用圆的画操作 */
        redCircle.draw();
        greenCircle.draw();
    }
}
           

有一个桥接口,包含一个画圆的方法;两种实现接口的桥;一个抽象产品类(构造函数传入画圆操作),画圆的方法抽象;一个继承抽象产品类的子类(与父类构造函数不同);客户端,构建产品,并且传入桥,然后调用产品的画操作。 与Strategy进行比较

桥接模式 策略模式
强调双方的run time delegation linking,在运行时通过delegation加以组合, 并永久保存这种delegation关系。 强调一方run-time使用另一方的“算法”,delegation是临时的

2.2.2、proxy(代理模式)

某个对象比较“敏感”/“私密”/“贵重”,不希望被client直接访问到,故设置proxy,在二者之间建立防火墙。

继承树

(二)面向可维护性的Java设计模式

举例

/* 接口 */
public interface Image {
    void display();
}
/* 子类 */
public class RealImage implements Image {
    private String fileName;
    public RealImage(String fileName){
        this.fileName = fileName;
        loadFromDisk(fileName);
    }
    @Override
    public void display() {…}
    /* 每次创建都要装载,代价高 */
    private void loadFromDisk(String fileName){…}
}
/* 代理 */
public class ProxyImage implements Image {
    private Image realImage;
    private String fileName;
    /* 不需要在构造时候从文件装载 */
    public ProxyImage fileName){
        this.fileName = fileName;
    }
    @Override
    public void display() {
        /* 加载代价高,如果发现装载,则delegation,否则装载 */
        if(realImage == null){
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}
/* 客户端 */
Image image = new ProxyImage(“pic.jpg");
image.display(); 
           

在客户端与实际产品类之间建立代理,通过判断,来进行下一步抉择(是否执行装载),可以降低代价。实现是,有一个产品接口,一个产品类,一个代理类,代理类中对于产品类中的高代价操作进行判断,看是否有执行的必要,若需要,则delegation到产品类中,否则进行下一步操作。

与适配器比较

适配器模式 代理模式
消除不兼容,目的是B以客户端期望的同一方式与A建立联系(通过创建适配器,内部进行delegation) 隔离对复杂对象的访问,降低难度、代价(例如例子),定位在访问、使用行为

2.2.3、composite(组合模式)

继承树

(二)面向可维护性的Java设计模式

举例:

/* 组合实现类-雇员 */
public class Employee {
    private String name;
    /* 下属 */
    private List<Employee> subordinates;
    public Employee(String name) {
        this.name = name;
        subordinates = new ArrayList<Employee>();
    }
    /* 添加下属 */
    public void add(Employee e) {
        subordinates.add(e);
    }
    public void remove(Employee e) {
        subordinates.remove(e);
    }
    public List<Employee> getSubordinates(){
        return subordinates;
    }
    public String toString(){…}
}
/* 客户端 */
    /* 创建四个对象 */
    Employee CEO = new Employee("John");
    Employee headSales = new Employee("Robert");
    Employee clerk1 = new Employee("Laura");
    Employee clerk2 = new Employee("Bob");
    /* 添加两个下属 */
    CEO.add(headSales);
    CEO.add(headMarketing);
    /* 添加下属 */
    headSales.add(clerk1);
    clerk1.add(clerk2);
    System.out.println(CEO);
    for (Employee headEmployee : CEO.getSubordinates()) {
        System.out.println(headEmployee);
        for (Employee employee : headEmployee.getSubordinates()) {
            System.out.println(employee);
        }
    }
           

从客户端可以看出,具有明显的迭代特征;这种特征,主要依赖于组合实现类中的List数组,保存Employee对象,以及相关的操作。

组合模式 装饰器模式
在同类型的对象之间建立起树型层次结构,一个上层对象可包含多个下层对象 强调的是同类型之间的特性增加问题,他们之间是平等的,区别在于拥有特性的多少,每个装饰只作用于一个对象
2.3、行为类模式

2.3.1、observer(观察者模式)

继承树

(二)面向可维护性的Java设计模式

举例

/**
* “粉丝”对“偶像”感兴趣,希望随时得知偶像的一举一动
* 粉丝到偶像那里注册,偶像一旦有新闻发生,就推送给已注册的粉丝
* (回调callback粉丝的特定功能)
*/
/* 主对象类-偶像 */
public class Subject {
    /* 维持一组粉丝 */
    private List<Observer> observers = new ArrayList<Observer>();
    private int state;
    public int getState() { 
        return state; 
    }
    /* 改变状态,并通知所有粉丝 */
    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }
    /* 注册粉丝 */
    public void attach(Observer observer){
        observers.add(observer); 
    }
    /* 通知所有粉丝 */
    public void notifyAllObservers(){
        for (Observer observer : observers) {
            /* 回调粉丝的update方法,通知 */
            observer.update();
        }
    }
}
/* 粉丝抽象接口 */
public abstract class Observer {
    protected Subject subject;
    public abstract void update();
}
/* 粉丝实现子类 */
public class BinaryObserver extends Observer{
    public BinaryObserver(Subject subject){
        this.subject = subject;
        /* 注册 */
        this.subject.attach(this);
    }
    /* 偶像回调的方法 */
    @Override
    public void update() {
        System.out.println( "Binary String: " + Integer.toBinaryString(subject.getState() ) );
    }
}
/* 客户端 */
public class ObserverPatternDemo {
    public static void main(String[] args) { 
        /* 一个偶像 */
        Subject subject = new Subject();
        /* 三个粉丝 */
        new HexaObserver(subject);
        new OctalObserver(subject);
        new BinaryObserver(subject);
        /* 更新状态 */
        System.out.println("First state change: 15");
        subject.setState();
        System.out.println("Second state change: 10");
        subject.setState();
    }
}
           

分析,一个偶像类,维持一组粉丝,当状态改变时,回调粉丝的

update

函数通知;另一方面,粉丝可以通过创建时,在偶像对象中注册。

在Java中提供了专门的接口,

Observable

抽象类,可以直接派生子类,构造偶像

Observer

接口,实现该接口,构造粉丝

(二)面向可维护性的Java设计模式

2.3.2、visitor(访问者模式)

对特定类型的object的特定操作(visit),在运行时将二者动态绑定到一起,该操作可以灵活更改,无需更改被visit的类。

本质上:将数据和作用于数据上的某种/些特定操作分离开来。

继承树

(二)面向可维护性的Java设计模式

举例:

/* 抽象对象接口 */
    public interface ItemElement {
    public int accept(ShoppingCartVisitor visitor);
}
/* 实例对象子类Book */
public class Book implements ItemElement{
    private double price;
    ...
    /* 将处理数据的功能delegate到外部传入的visitor */
    int accept(ShoppingCartVisitor visitor) {
        visitor.visit(this);
    }
}
/* 实例对象子类- */
public class Fruit implements ItemElement{
    private double weight;
    ...
    int accept(ShoppingCartVisitor visitor) {
        visitor.visit(this);
    }
}
/* 清单Visitor接口 */
public interface ShoppingCartVisitor {
    int visit(Book book);
    int visit(Fruit fruit);
}
/* Visitor子类,返回价格 */
public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
    public int visit(Book book) {
        int cost=;
        if(book.getPrice() > ){
            cost = book.getPrice()-;
        }else
            cost = book.getPrice();
        System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
        return cost;
    }
    public int visit(Fruit fruit) {
        int cost = fruit.getPricePerKg()*fruit.getWeight();
        System.out.println(fruit.getName() + " cost = "+cost);
        return cost;
    }
}
/* 客户端 */
public class ShoppingCartClient {
    public static void main(String[] args) {

        ItemElement[] items = new ItemElement[]{
        new Book(, "1234"),new Book(, "5678"),
        new Fruit(, , "Banana"), new Fruit(, , "Apple")};
        /* 计算价格 */
        int total = calculatePrice(items);
        System.out.println("Total Cost = "+total);
        }
    private static int calculatePrice(ItemElement[] items) {
        ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
        int sum=;
        for(ItemElement item : items)
        /* 传入visitor */
            sum = sum + item.accept(visitor);
        return sum;
    }
}
           

分析,抽象货物接口,有一个accept方法,用来接收visitor;两个实现接口的类Book和Fruit,accpt方法,调用visitor的visit的方法,得到价格;一个购物清单访问者接口,访问者子类实现接口,实现visit方法,根据传入的对象,返回价格;客户端,创建一组货物,和一个访问者对象,将访问者对象传入每一个货物,计算价格。

访问者模式 vs 迭代器模式 访问者模式 vs 策略模式
访问者模式 迭代器模式 访问者模式 策略模式
在特定的ADT上执行某种特定操作(accept(visitor)),但该操作不是在ADT内部实现,而是delegate到独立的visitor对象(visitor.visit(this)),客户端可灵活扩展、改变visitor的操作算法,而不影响ADT 以遍历的方式访问集合数据而无需暴露其内部表示,将”遍历”这项操作delegate到外部的iterator(继承Iterable接口,实现iterator方法,继承Iterator接口实现一个自定义的iterator类) Visitor强调是的外部定义某种对ADT的操作,该操作于ADT自身关系不大(只是访问ADT),故ADT内部只需要开放accept(visitor)即可,client通过它设定visitor操作并在外部调用。 Strategy则强调是对ADT内部某些要实现的功能的相应算法的灵活替换。这些算法是ADT功能的重要组成部分,只不过是delegate到外部strategy类而已。
visitor是站在外部client的角度,灵活增加对ADT的各种不同操作(哪怕ADT没实现该操作),strategy则是站在内部ADT的角度,灵活变化对其内部功能的不同配置。
2.4、基于状态的模式

2.3.4、state(状态模式)

继承树

(二)面向可维护性的Java设计模式

举例

/* 状态接口 */
//状态接口
public interface State {
    State move(char c);
    boolean accept();
}
/* 状态1 */
class State1 implements State {
    static State1 instance = new State1(); //singleton模式
    private State1() {}
    public State move (char c) {
        switch (c) {
            case 'a': return State2.instance;
            case 'b': return State1.instance;
            default: throw new IllegalArgumentException();
        }
    }
    public boolean accept() {
        return false;
    } //该状态非可接受状态
}
/* 状态2 */
class State2 implements State {
    static State2 instance = new State2();
    private State2() {}
    public State move (char c) {
        switch (c) {
            case 'a': return State1.instance;
            case 'b': return State1.instance;
            default: throw new IllegalArgumentException();
        }
    }
    public boolean accept() {return true;} //此为接收状态
}
/* 主类,状态转换 */
class Context {
    State state; //保存对象的状态
    //设置初始状态
    public Context(State s) {state = s;}
    //接收外部输入,开启状态转换
    public void move(char c) { state = state.move(c); }
    //判断是否达到合法的最终状态
    public boolean accept() { return state.accept(); }
    public State getState() { return this.state; }
}
/* 客户端 */
public static void main(String[] args) {
    Context context = new Context(new State1());
    for (int i = ; i < args.length; i++) {
        context.move(args[i]);
        if(context.accept())
            break;
    }
}
           

一个状态接口,两个实现状态接口的子类;一个执行状态转换的类;以及客户端,客户端输入状态,执行类状态改变,直到输入状态为接收状态,停止。

本质上就是delegation,将执行类中的状态转换委派到状态类中,状态类进行转换,并返回新的转换后的状态。

2.3.5、memento(备忘录模式)

Originator:需要备忘的类;

Caretaker:添加Originator的备忘记录和恢复;

Memento:备忘录,记录Originator对象的历史状态。

继承树

(二)面向可维护性的Java设计模式

举例

/* 备忘录,记录状态 */
class Memento {
    private State state;
    public Memento(State state) {
        this.state = state;
    }
    public State getState() {
        return state;
    }
}
/* 主类,需要备忘的类 */
class Originator {
    private State state;
    public void setState(State state) {
        System.out.println("Originator: Setting state to " + state.toString());
        this.state = state;
    }
    public Memento save() {
        System.out.println("Originator: Saving to Memento.");
        return new Memento(state);
    }
    public void restore(Memento m) {
        state = m.getState();
        System.out.println("Originator: State after restoring from Memento: " + state);
    }
}
/* 记录所有的状态 */
class Caretaker {
    private ArrayList<Memento> mementos = new ArrayList<>();
    public void addMemento(Memento m) {
        mementos.add(m);
    }
    public Memento getMemento() {
        return mementos.get();
    }
}
/* 客户端 */
public class Demonstration {
    public static void main(String[] args) {
        /* 备忘类,保存历史状态 */
        Caretaker caretaker = new Caretaker();
        /* 主类 */
        Originator originator = new Originator();
        /* 设置状态,备忘状态 */
        originator.setState("State1");
        originator.setState("State2");
        caretaker.addMemento( originator.save() );
        originator.setState("State3");
        caretaker.addMemento( originator.save() );
        originator.setState("State4");
        originator.restore( caretaker.getMemento() );
    }
}
           

客户端创建一个主类(需要备忘的类),一个保存状态的类,当主类对象改变状态时,使用状态保存类保存。

保存状态的类可以有更多的操作,比如,可以状态回滚。

继续阅读