"Try in C! Design pattern" This time is the Memento pattern. In a word, it's a DB rollback. If you think about it carefully, I think it's a useful pattern.
List of design patterns Description of the created library package The public code is here
The explanation of wikipedia is as follows.
The memento pattern (English: Memento pattern, Japan: Memento pattern) is one of the software design patterns that provides the ability to return an object to its previous state (by rollback).
It's simple. Even if you look at Techscore's explanation and the class diagram below, Originator has a mechanism to return to the original state using the Mememt class that holds the state.
Looking back on the past, I wondered what it was used for. There were quite a few use cases that seemed useful.
If you are using DB, you can use the rollback function, but if you have a system with a simple data storage mechanism, you do not need to use DB, so if you want to restore it in case of an error, an error will occur. Sometimes I see it implemented in a squeaky code.
I thought it would be unavoidable if I didn't need to use the DB, but I often feel motivated to "remember the previous state".
Especially when developing the screen, press the "Back" button to return to the original screen state. Rollback processing like this is necessary in various ways. Enable this previous View and this View so that this button can be used.
When I developed an Android application as a hobby before, what is the smart way to do this? I was developing while worrying about it all the time. At that time
--A class dedicated to screen state management transition is set up, and when the screen is transitioned, the transition is returned as "Next is what state" and "back is what state".
I was doing something like that. Change the View layout while being aware of the previous state. Like this I feel like I've done my best as an amateur, but I'm sure I'll die because of the large amount of changes to the screen changes.
** If you don't use Memento **
Button event management class
//Event management class for each button
public class ActivityListenerPresenter {
public static ActivityListenerPresenterImple mInstance;
public static ActivityListenerPresenterImple getInstance() {
if(mInstance == null) mInstance = new ActivityListenerPresenterImple();
return mInstance;
}
//Perform screen transition for each button event
...
//Pushed back
public static boolean goBack() {
return getInstance().goBack();
}
}
Button event management class(This mounting side
public class ActivityListenerPresenterImple {
...
public boolean goBack() {
//Status acquisition
ActivityListenerState prevState = mActivityStateAction.getPrev();
Log.v(TAG_LOG, "Prev state=" + prevState);
goNext(prevState);
return true;
}
private void goNext(ActivityListenerState state) {
//Status acquisition
mActivityStateAction = getActivityStateAction(state);
//Display the screen according to the state
mActivityStateAction.showCurrent();
}
private ActivityStateAction getActivityStateAction(ActivityListenerState state) {
Log.v(TAG_LOG, "getActivityStateAction=" + state);
ActivityStateAction action=null;
switch(state) {
case MYVIDEO_LIST:
action = new ActivityStateActionMYVIDEO_LIST();
break;
case MYVIDEO_RUN:
action = new ActivityStateActionMYVIDEO_RUN();
break;
...
}
return action;
}
//I will do my best to implement what the prev will be in each state
private interface ActivityStateAction{
//Actual view switching
public void showCurrent();
//Do your best to return to prev
public ActivityListenerState getPrev();
}
For example, using the idea of mement, it may have been possible to memorize the previous state at the time of state transition and restore it even without getPrev
.
It won't be simple like this, but this one seems to have better code volume and readability.
** Expectations when using Memento **
Button event management class(This mounting side
public class ActivityListenerPresenterImple {
...
public boolean goBack() {
//Status acquisition
mActivityStateAction = setMementPrevActivityStateAction()
//Display the screen according to the state
mActivityStateAction.showCurrent();
return true;
}
private void goNext(ActivityListenerState state) {
//Keep the previous state
mementPrevActivityStateAction(mActivityStateAction);
//Status acquisition
mActivityStateAction = getActivityStateAction(state);
//Display the screen according to the state
mActivityStateAction.showCurrent();
}
///getActivityStateAction remains unchanged
//Isn't the interface of each state only good with showCurrent?
private interface ActivityStateAction{
//Actual view switching
public void showCurrent();
//public ActivityListenerState getPrev();
}
When I recall various things, I tried to make a library of memento and use cases where I can see the scenes I want. The contents I am doing are almost the same as at the time of prototype.
--Record memories (instance information) in the library. ――Be able to dig up the memories you remember.
Basically, rollback at the time of error is assumed.
This time it is supposed to be disposable every time, so there is no class design. So omitted.
――It's easy not to remember what kind of state you should return to
--After all, the process of digging up memories is left to the implementation user
Confirmed on Ubuntu 18.04 Desktop, CentOS 7.5.1804. I think it works on Linux.
mement.h
/*Mement Register definition*/
struct mement_register_t;
typedef struct mement_register_t *MementRegister;
/*User-implemented function definition. The default is memcpy and free do nothing(Body instance destroyed with Mement Register*/
struct mement_method_t {
/*Since the instance of mement is in the library, its constructor*/
void (*constructor) (void *instance, void * base, size_t base_length);
/*copy of memento*/
void (*copy) (void *broken_instance, void * base, size_t base_length);
/*Release of memento. The base entity is acquired together with Mement Register, so it is not freed.*/
void (*free) (void * base, size_t base_length);
};
typedef struct mement_method_t mement_method_t;
/*mement registration*/
MementRegister mement_register(void * base, size_t base_length, mement_method_t * method);
/*unregister memento*/
void mement_unregister(MementRegister this);
/*Memento memories*/
void mement_remember(MementRegister this, void * broken_instance, int is_unregister_mement);
It is located below. https://github.com/developer-kikikaikai/design_pattern_for_c/tree/master/mement
You don't need a sample, right? Just remember the data you held. Please refer to the code of mement / test if necessary.
Record your memories so that you can remember them. I think it's a simple but excellent idea. I made a mistake in the git operation of memento and deleted the whole code including the test.
It's important to keep a record
Recommended Posts