状态模式的定义:Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.(当一个对象在状态改变时允许其改变行为,这个对象看起来像其改变了其类)。
一个对象可以在声明周期内修改自己的状态,但是却不能在生命周期内修改自己所属的类。运用状态模式,可以得到一个优雅的折衷。
状态模式的核心是封装,状态的变化引起了行为俄变更,从外部看起来就像是这个对象对应的类发生了改变一样,状态模式的通用类图如下图所示:
state:抽象状态角色,为接口或者抽象类,负责对象操作接口的定义,并且封装环境角色以实现状态切换。
concretestate:具体状态角色,每一个具体状态必须完成两个职责,本状态的行为管理以及趋向状态管理,通俗的讲,就是本状态下要做的事情,以及本状态如何过渡到其它状态。
context:定义客户端需要的接口,并且负责具体状态的切换,是使用状态的一方。
Client:用户程序,main函数等等,可以看作是舞台,场景类。
本用例状态模式UML类图:
状态模式代码实现:
#include <thread>
#include <memory>
#include <mutex>
#include <iostream>
class wrapper
{
public:
wrapper(int x, int y) {
this->obj1 = x;
this->obj2 = y;
//sta = new state1(1);
sta = std::make_shared<state1>(1);
std::cout << __func__ << __LINE__ << std::endl;
}
~wrapper(void) {
//delete sta;
std::cout << __func__ <<" "<< __LINE__ << std::endl;
}
void member1() {
while(1) {
m.lock();
r_m.lock();
std::cout << "i am member1 " << "obj1 = " << this->obj1 << " obj2 = " << this->obj2 << " id " << std::this_thread::get_id() << std::endl;
r_m.unlock();
m.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
void member2(const char *arg1, unsigned arg2) {
while(1) {
m.lock();
r_m.lock();
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
sta->show_state(*this);
r_m.unlock();
m.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
std::thread member1thread() {
std::thread th1;
th1 = std::thread(&wrapper::member1, this);
return th1;
}
std::thread member2thread(const char *arg1, unsigned arg2) {
return std::thread(&wrapper::member2, this, arg1, arg2);
}
int test_member_function(void)
{
return this->obj1 + this->obj2;
}
void state_verbose(void)
{
sta->show_state(*this);
}
class state
{
public:
virtual void show_state(wrapper &w) = 0;
};
void set_state(std::shared_ptr<wrapper::state> s)
{
sta = s;
}
class state1: public state
{
public:
state1(int st)
{
test1 = st;
}
void show_state(wrapper &w)
{
std::cout << "now in state 1" << std::endl;
std::shared_ptr<wrapper::state> s = std::make_shared<state2>(2);
w.set_state(s);
w.state_verbose();
}
private:
int test1;
};
class state2: public state
{
public:
state2(int st)
{
test2 = st;
}
void show_state(wrapper &w)
{
std::cout << "now in state 2" << std::endl;
std::shared_ptr<wrapper::state> s = std::make_shared<state3>(3);
w.set_state(s);
w.state_verbose();
}
private:
int test2;
};
class state3: public state
{
public:
state3(int st)
{
test3 = st;
}
void show_state(wrapper &w)
{
std::cout << "now in state 3" << std::endl;
std::shared_ptr<wrapper::state> s = std::make_shared<state1>(1);
w.set_state(s);
//w.state_verbose();
}
private:
int test3;
};
private:
int obj1;
int obj2;
std::mutex m;
std::recursive_mutex r_m;
//class state *sta;
std::shared_ptr<wrapper::state> sta;
};
void f1(int n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "thread " << n << " executing\n";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int main(void)
{
int ret;
//wrapper *w = new wrapper(1, 2);
//std::shared_ptr<wrapper> w = std::make_shared<wrapper>(1, 2);
auto w = std