天天看點

(二)面向可維護性的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() );
    }
}
           

用戶端建立一個主類(需要備忘的類),一個儲存狀态的類,當主類對象改變狀态時,使用狀态儲存類儲存。

儲存狀态的類可以有更多的操作,比如,可以狀态復原。

繼續閱讀