備忘錄模式

備忘錄模式

定義

在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,這樣,之後就能夠將該對象恢復到原先保存的狀態。android

使用場景

  • 須要保存一個對象在摸一個時刻的狀態或部分狀態
  • 若是用一個接口來讓其餘對象獲得這些狀態,將會暴露對象的實現細節並破壞對象的封裝性,一個對象不但願外界直接訪問其內部狀態,經過中間對象能夠直接訪問其內部狀態

結構

  • 原發器 Originatorbash

    負責建立一個備忘錄,能夠記錄、恢復自身的內部狀態。同時 Originator 還能夠根據須要決定 Memento 存儲自身的哪些內部狀態。ide

  • 備忘錄 Mementoui

    備忘錄角色,用於儲存 Originator 內部狀態,並能夠防止 Originator 之外的對象訪問 Mementothis

  • 負責人 Caretakerspa

    負責存儲備忘錄,不能對備忘錄的內容進行操做和訪問,只可以將備忘錄傳遞給其餘對象設計

簡單實現

一個簡單的便籤功能Demorest

/**
 * @author jc
 * @time 2018/4/30 下午5:59
 * @desc 備忘錄角色,肯定須要保存的內部狀態
 */

public class Memoto {
    public String text;
    public int cursor;
}

複製代碼
/**
 * @author jc
 * @time 2018/4/30 下午6:07
 * @desc NoteEditText充當Originator角色,建立和恢復備忘錄
 */

public class NoteEditText extends android.support.v7.widget.AppCompatEditText {
    public NoteEditText(Context context) {
        this(context, null);
    }


    public NoteEditText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public NoteEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 建立備忘錄對象 存儲編輯的信息
     *
     * @return
     */
    public Memoto createMemoto() {
        Memoto memoto = new Memoto();
        memoto.text = getText().toString();
        memoto.cursor = getSelectionStart();
        return memoto;
    }

    /**
     * 從備忘錄中恢復數據
     *
     * @param memoto
     */
    public void restore(Memoto memoto) {
        setText(memoto.text);
        setSelection(memoto.cursor);
    }

}
複製代碼
/**
 * @author jc
 * @time 2018/4/30 下午5:56
 * @desc 負責管理 Memoto 對象
 */

public class NoteCaretaker {

    /**
     * 最大存儲數量
     */
    private static final int MAX = 20;
    List<Memoto> mMemotos = new ArrayList<>(MAX);
    int mIndex = 0;

    /**
     * 保存備忘錄記錄到記錄列表中
     *
     * @param memoto
     */
    public void saveMemoto(Memoto memoto) {
        if (mMemotos.size() > MAX) {
            mMemotos.remove(0);
        }
        mMemotos.add(memoto);
        mIndex = mMemotos.size() - 1;
    }

    /**
     * 獲取上一個存檔信息
     *
     * @return
     */
    public Memoto getPrevMemoto() {

        mIndex = mIndex > 0 ? --mIndex : mIndex;
        return mMemotos.get(mIndex);
    }

    /**
     * 獲取下一個存檔信息,至關於恢復
     *
     * @return
     */
    public Memoto getNextMemoto() {
        mIndex = mIndex < mMemotos.size() - 1 ? ++mIndex : mIndex;
        return mMemotos.get(mIndex);
    }

}
複製代碼
public class MementoActivity extends AppCompatActivity implements View.OnClickListener {


    NoteEditText noteEditText;
    TextView mSavaTv;
    TextView mUndoBtn;
    TextView mRedoBtn;

    NoteCaretaker noteCaretaker = new NoteCaretaker();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_memento);

        initViews();
    }

    private void initViews() {
        noteEditText = findViewById(R.id.note_et);
        mUndoBtn = findViewById(R.id.undo_btn);
        mUndoBtn.setOnClickListener(this);
        mRedoBtn = findViewById(R.id.redo_btn);
        mRedoBtn.setOnClickListener(this);
        mSavaTv = findViewById(R.id.save_tv);
        mSavaTv.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.undo_btn:
                noteEditText.restore(noteCaretaker.getPrevMemoto());
                makeToast("撤銷 : ");
                break;
            case R.id.redo_btn:
                noteEditText.restore(noteCaretaker.getNextMemoto());
                makeToast("恢復 : ");
                break;
            case R.id.save_tv:
                noteCaretaker.saveMemoto(noteEditText.createMemoto());
                makeToast("保存 : ");
                break;
            default:
                break;
        }
    }

    private void makeToast(String s) {
        Toast.makeText(this, s + " 光標位置 :"
                + noteEditText.getSelectionStart(), Toast.LENGTH_SHORT).show();

        Log.v(getClass().getSimpleName(), s + noteEditText.getText());
    }
}
複製代碼

小結

備忘錄模式的關鍵在於設計備忘錄類和負責人類,須要防止原發器之外的其它對象訪問備忘錄code

備忘錄對象一般封裝了原發器的部分或全部狀態信息,並且這些信息不能被其餘對象訪問;也就是說不能在備忘錄對象以外保存原發器的狀態對象

原發器能夠調用備忘錄的因此信息,容許原發器訪問先前狀態全部數據

負責人只負責備忘錄的保存並將備忘錄對象傳遞給其餘對象

其餘對象只須要從負責人處取出備忘錄對象並將原發器對象的狀態恢復,而無需關心備忘錄的保存細節

思考

  • 備忘錄模式與命令模式實現撤銷時的異同
相關文章
相關標籤/搜索