在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,這樣,之後就能夠將該對象恢復到原先保存的狀態。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
備忘錄對象一般封裝了原發器的部分或全部狀態信息,並且這些信息不能被其餘對象訪問;也就是說不能在備忘錄對象以外保存原發器的狀態對象
原發器能夠調用備忘錄的因此信息,容許原發器訪問先前狀態全部數據
負責人只負責備忘錄的保存並將備忘錄對象傳遞給其餘對象
其餘對象只須要從負責人處取出備忘錄對象並將原發器對象的狀態恢復,而無需關心備忘錄的保存細節