catalogue
18. Responsibility chain model
18. Responsibility chain model
Responsibility chain mode: make multiple objects have the opportunity to process the request, so as to avoid the coupling relationship between the sender and receiver of the request. Connect these objects into a chain and pass the request along the chain until an object processes it.
The handler in the responsibility chain is responsible for processing the request. The customer only needs to send the request to the responsibility chain without paying attention to the processing details of the request and the transmission of the request. All responsibility chains decouple the sender of the request from the handler of the request.
/* * Key code: indicate its superior in Handler, judge whether it is appropriate in handleRequest(), and pass it to the superior if it is not appropriate. */ #include <iostream> using namespace std; enum RequestLevel { Level_One = 0, Level_Two, Level_Three, Level_Num }; //The abstract Handler role provides a unified interface to the responsibility chain. class Leader { public: Leader(Leader* leader):m_leader(leader){} virtual ~Leader(){} virtual void handleRequest(RequestLevel level) = 0; protected: Leader* m_leader; }; //Concrete Handler role class Monitor:public Leader //Chain buckle 1 { public: Monitor(Leader* leader):Leader(leader){} void handleRequest(RequestLevel level) { if(level < Level_Two) { cout << "Mointor handle request : " << level << endl; } else { m_leader->handleRequest(level); } } }; //Concrete Handler role class Captain:public Leader //Chain buckle 2 { public: Captain(Leader* leader):Leader(leader){} void handleRequest(RequestLevel level) { if(level < Level_Three) { cout << "Captain handle request : " << level << endl; } else { m_leader->handleRequest(level); } } }; //Concrete Handler role class General:public Leader //Chain buckle 3 { public: General(Leader* leader):Leader(leader){} void handleRequest(RequestLevel level) { cout << "General handle request : " << level << endl; } }; int main() { Leader* general = new General(nullptr); Leader* captain = new Captain(general); Leader* monitor = new Monitor(captain); monitor->handleRequest(Level_One); delete monitor; monitor = nullptr; delete captain; captain = nullptr; delete general; general = nullptr; return 0; }
18.1 example 2
Make multiple objects have the opportunity to process the request, so as to avoid the coupling relationship between the sender and receiver of the request. Connect these objects into a chain and pass the request along the chain until an object processes it.
The idea is very simple, considering that employees ask for a raise.
There are three levels of managers in the company: general manager, director and manager. If an employee asks for a raise, he should apply to the manager in charge. If the amount of raise is within the authority of the manager, the manager can approve it directly, otherwise the application will be submitted to the director. The handling method of the director is the same, and the general manager can handle all requests. This is the typical responsibility chain mode. The processing of requests forms a chain until an object processes the request. UML diagram of this example is given.
The implementation of the code is relatively simple, as shown below:
//Abstract Manager class Manager { protected: Manager *m_manager; string m_name; public: Manager(Manager *manager, string name):m_manager(manager), m_name(name){} virtual void DealWithRequest(string name, int num) {} }; //manager class CommonManager: public Manager { public: CommonManager(Manager *manager, string name):Manager(manager,name) {} void DealWithRequest(string name, int num) { if(num < 500) //Within the authority of the manager { cout<<"manager"<<m_name<<"approval"<<name<<"Raise salary"<<num<<"element"<<endl<<endl; } else { cout<<"manager"<<m_name<<"If it cannot be handled, it shall be handled by the director"<<endl; m_manager->DealWithRequest(name, num); } } }; //chief inspector class Majordomo: public Manager { public: Majordomo(Manager *manager, string name):Manager(manager,name) {} void DealWithRequest(string name, int num) { if(num < 1000) //Within the authority of the director { cout<<"chief inspector"<<m_name<<"approval"<<name<<"Raise salary"<<num<<"element"<<endl<<endl; } else { cout<<"chief inspector"<<m_name<<"If it cannot be handled, it shall be handled by the general manager"<<endl; m_manager->DealWithRequest(name, num); } } }; //general manager class GeneralManager: public Manager { public: GeneralManager(Manager *manager, string name):Manager(manager,name) {} void DealWithRequest(string name, int num) //The general manager can handle all requests { cout<<"general manager"<<m_name<<"approval"<<name<<"Raise salary"<<num<<"element"<<endl<<endl; } }; // The customer call method is: //Test case int main() { Manager *general = new GeneralManager(NULL, "A"); //Set up a superior. The general manager has no superior Manager *majordomo = new Majordomo(general, "B"); //Set up superior Manager *common = new CommonManager(majordomo, "C"); //Set up superior common->DealWithRequest("D",300); //Employee D asked for a raise common->DealWithRequest("E", 600); common->DealWithRequest("F", 1000); delete common; delete majordomo; delete general; return 0; }
reference material: https://blog.csdn.net/wuzhekai1985/article/details/6673892
reference material: https://www.cnblogs.com/chengjundu/p/8473564.html
19. Observer mode
Observer mode: defines a one to many dependency between objects. When the state of an object changes, all objects that depend on it should be notified and updated automatically.
Basically, the observer and the observer must contain two roles.
1. The observed object itself should contain a container to store the observer object. When the observed object itself changes, all the observer objects in the container should be notified to update automatically.
2. The observer object can be registered in the of the observer. After registration, it can detect the changes of the observer and receive the notification of the observer. Of course, the observer can also be cancelled and the monitoring of the observed can be stopped.
/* * Key code: add an ArrayList in the target class to store the observers. */ #include <iostream> #include <list> #include <memory> using namespace std; class View; //Observer abstract class data model class DataModel { public: virtual ~DataModel(){} virtual void addView(View* view) = 0; virtual void removeView(View* view) = 0; virtual void notify() = 0; //Notification function }; //Observer abstract class view class View { public: virtual ~View(){ cout << "~View()" << endl; } virtual void update() = 0; virtual void setViewName(const string& name) = 0; virtual const string& name() = 0; }; //Specific observed class, integer model class IntDataModel:public DataModel { public: ~IntDataModel() { m_pViewList.clear(); } virtual void addView(View* view) override { shared_ptr<View> temp(view); auto iter = find(m_pViewList.begin(), m_pViewList.end(), temp); if(iter == m_pViewList.end()) { m_pViewList.push_front(temp); } else { cout << "View already exists" << endl; } } void removeView(View* view) override { auto iter = m_pViewList.begin(); for(; iter != m_pViewList.end(); iter++) { if((*iter).get() == view) { m_pViewList.erase(iter); cout << "remove view" << endl; return; } } } virtual void notify() override { auto iter = m_pViewList.begin(); for(; iter != m_pViewList.end(); iter++) { (*iter).get()->update(); } } private: list<shared_ptr<View>> m_pViewList; }; //Specific Observer class table view class TableView : public View { public: TableView() : m_name("unknow"){} TableView(const string& name) : m_name(name){} ~TableView(){ cout << "~TableView(): " << m_name.data() << endl; } void setViewName(const string& name) { m_name = name; } const string& name() { return m_name; } void update() override { cout << m_name.data() << " update" << endl; } private: string m_name; }; int main() { /* * It should be added here that in this example code, once the View is registered to the DataModel class, the DataModel will be automatically resolved when it is parsed * The View object stored in the internal container, so the registered View object does not need to be delete d manually, and then deleting the View object will make an error. */ View* v1 = new TableView("TableView1"); View* v2 = new TableView("TableView2"); View* v3 = new TableView("TableView3"); View* v4 = new TableView("TableView4"); IntDataModel* model = new IntDataModel; model->addView(v1); model->addView(v2); model->addView(v3); model->addView(v4); model->notify(); cout << "-------------\n" << endl; model->removeView(v1); model->notify(); delete model; model = nullptr; return 0; }
19.1 example 2
Defines a one to many dependency between objects. When the state of an object changes, all objects that depend on it are notified and automatically updated. It also has two aliases, dependencies and publish subscribe.
Take Blog subscription as an example. When a blogger publishes a new article, that is, the blogger's status changes, those subscribed readers will receive a notice and take corresponding actions, such as reading an article or collecting it. There is a one to many dependency between bloggers and readers. The corresponding UML diagram design is given below.
You can see that there is a linked list of observers (subscribers) in the blog class. When the status of the blog changes, Notify all observers through the Notify member function to tell them that the status of the blog has been updated. The observer obtains the status information of the blog through the Update member function. The code implementation is not difficult. An implementation of C + + is given below.
//Observer class Observer { public: Observer() {} virtual ~Observer() {} virtual void Update() {} }; //Blog class Blog { public: Blog() {} virtual ~Blog() {} void Attach(Observer *observer) { m_observers.push_back(observer); } //Add observer void Remove(Observer *observer) { m_observers.remove(observer); } //Remove observer void Notify() //Notify the observer { list<Observer*>::iterator iter = m_observers.begin(); for(; iter != m_observers.end(); iter++) (*iter)->Update(); } virtual void SetStatus(string s) { m_status = s; } //Set status virtual string GetStatus() { return m_status; } //Get status private: list<Observer* > m_observers; //Observer list protected: string m_status; //state }; // The above is the base class of observer and blog, which defines the general interface. Blog class mainly completes the operations of adding, removing and notifying observers. Setting and obtaining status is only a default implementation. Their corresponding subclass implementations are given below. //Specific blog category class BlogCSDN : public Blog { private: string m_name; //Blogger name public: BlogCSDN(string name): m_name(name) {} ~BlogCSDN() {} void SetStatus(string s) { m_status = "CSDN notice : " + m_name + s; } //Specific setting status information string GetStatus() { return m_status; } }; //Specific observer class ObserverBlog : public Observer { private: string m_name; //Observer name Blog *m_blog; //Observation of the blog, of course, in the form of a linked list is better, you can observe multiple blogs public: ObserverBlog(string name,Blog *blog): m_name(name), m_blog(blog) {} ~ObserverBlog() {} void Update() //Get update status { string status = m_blog->GetStatus(); cout<<m_name<<"-------"<<status<<endl; } }; // Customer usage: //Test case int main() { Blog *blog = new BlogCSDN("wodehao0808"); Observer *observer1 = new ObserverBlog("niuniu", blog); blog->Attach(observer1); blog->SetStatus("Publish rendering test"); blog->Notify(); delete blog; delete observer1; return 0; }
reference material: https://blog.csdn.net/wuzhekai1985/article/details/6674984
reference material: https://www.cnblogs.com/chengjundu/p/8473564.html
20. Status mode
State mode: allows an object to change its behavior when its internal state changes. Object appears to have modified its class. It can be used in two ways:
(1) the behavior of an object depends on its state, and it must change its behavior according to the state at runtime.
(2) an operation contains a large number of conditional statements with multiple branches, and these branches depend on the state of the object.
The example of this paper is the first case. Taking the war as an example, it is assumed that a war needs to go through four stages: early stage, middle stage, late stage and end. When the war is in different stages, the behavior of the war is different, that is to say, the behavior of the war depends on the stage and changes dynamically with the advance of time. The corresponding UML diagram is given below.
The implementation code is relatively simple. War class and State class are given. War class contains State object (pointer form).
class War; class State { public: virtual void Prophase() {} virtual void Metaphase() {} virtual void Anaphase() {} virtual void End() {} virtual void CurrentState(War *war) {} }; //Warfare class War { private: State *m_state; //Current status int m_days; //Duration of war public: War(State *state): m_state(state), m_days(0) {} ~War() { delete m_state; } int GetDays() { return m_days; } void SetDays(int days) { m_days = days; } void SetState(State *state) { delete m_state; m_state = state; } void GetState() { m_state->CurrentState(this); } }; Specific status classes are given: //The war is over class EndState: public State { public: void End(War *war) //Specific actions at the end stage { cout<<"The war is over"<<endl; } void CurrentState(War *war) { End(war); } }; //later stage class AnaphaseState: public State { public: void Anaphase(War *war) //Later specific behavior { if(war->GetDays() < 30) cout<<"The first"<<war->GetDays()<<"Day: at the end of the war, both sides fought to the death"<<endl; else { war->SetState(new EndState()); war->GetState(); } } void CurrentState(War *war) { Anaphase(war); } }; //metaphase class MetaphaseState: public State { public: void Metaphase(War *war) //Specific behavior in the medium term { if(war->GetDays() < 20) cout<<"The first"<<war->GetDays()<<"Day: in the middle of the war, it entered the stalemate stage, and both engines lost"<<endl; else { war->SetState(new AnaphaseState()); war->GetState(); } } void CurrentState(War *war) { Metaphase(war); } }; //early stage class ProphaseState: public State { public: void Prophase(War *war) //Specific behavior in the early stage { if(war->GetDays() < 10) cout<<"The first"<<war->GetDays()<<"Tian: at the beginning of the war, both sides came and went to test each other"<<endl; else { war->SetState(new MetaphaseState()); war->GetState(); } } void CurrentState(War *war) { Prophase(war); } }; // Usage: //Test case int main() { War *war = new War(new ProphaseState()); for(int i = 1; i < 40;i += 5) { war->SetDays(i); war->GetState(); } delete war; return 0; }
reference material: https://blog.csdn.net/wuzhekai1985/article/details/6675799