状态模式的定义: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::make_shared<wrapper>(1, 2);
std::thread tw1 = w->member1thread();
ret = w->test_member_function();
std::thread tw2 = w->member2thread("helloworld", 6);
std::thread t2(f1, 6); // pass by value
std::cout << "after starting, tw1 joinable: " << tw1.joinable() << " id " << tw1.get_id() << std::endl;
std::cout << "after starting, tw2 joinable: " << tw2.joinable() << " id " << tw2.get_id() << std::endl;
std::cout << "after starting, t2 joinable: " << t2.joinable() << " id " << t2.get_id() << std::endl;
std::thread tw3 = w->member2thread("hello", 100);
tw3.detach();
std::cout << "after starting, tw3 joinable: " << tw3.joinable() << std::endl;
t2.join();
tw1.join();
tw2.join();
return 0;
}
$ g++ -std=c++11 -O0 -g3 model.cpp -lpthread
make_shared会调用构造函数:
make_shared析构
#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(void) {
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(void) {
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;
std::cout << __func__ <<" "<<__LINE__ << std::endl;
}
~state1(void) {
std::cout << __func__ <<" "<<__LINE__ << std::endl;
}
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;
std::cout << __func__ <<" "<<__LINE__ << std::endl;
}
~state2(void) {
std::cout << __func__ <<" "<<__LINE__ << std::endl;
}
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;
std::cout << __func__ <<" "<<__LINE__ << std::endl;
}
~state3(void) {
std::cout << __func__ <<" "<<__LINE__ << std::endl;
}
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::make_shared<wrapper>(1, 2);
std::thread tw1 = w->member1thread();
ret = w->test_member_function();
std::thread tw2 = w->member2thread("helloworld", 6);
std::thread t2(f1, 6); // pass by value
std::cout << "after starting, tw1 joinable: " << tw1.joinable() << " id " << tw1.get_id() << std::endl;
std::cout << "after starting, tw2 joinable: " << tw2.joinable() << " id " << tw2.get_id() << std::endl;
std::cout << "after starting, t2 joinable: " << t2.joinable() << " id " << t2.get_id() << std::endl;
std::thread tw3 = w->member2thread("hello", 100);
tw3.detach();
std::cout << "after starting, tw3 joinable: " << tw3.joinable() << std::endl;
t2.join();
tw1.join();
tw2.join();
return 0;
}
智能指针
智能指针是一种RAll(资源获取即初始化)机制,用于在使用完动态分配的内存后,自动释放内存。防止内存泄漏,C++11标准引入了两种智能指针,std::unique_ptr和std::shared_ptr。
std::unique_ptr是独占指针,只能有一个智能指针拥有资源,不能复制和共享,当unique_ptr被销毁时,它所管理的资源也会被自动释放,使用std::move将unique_ptr的所有权转移给另一个unique_ptr.
std::shared_ptr,可以被多个智能指针共享,每个共享指针都维护一个引用记数,当引用记数为0时,自动释放资源,使用std::make_shared创建shared_ptr.
智能指针的实现原理可以分为两个主要部分,资源管理和拷贝控制。
资源管理:智能指针中需要管理指向动态分配内存的原始指针,通常是通过在构造函数中分配内存,在析构函数中释放内存来实现的。智能指针还需要提供一个可以访问被管理的对象的方法,通常是通过重载解引用运算符(*)和箭头运算符(->)来实现的。
拷贝控制:
智能指针需要对拷贝,赋值等操作进行控制,以确保资源被正确管理,常见的做法是使用引用计数来记录共享的指针数量,并且在拷贝或赋值时增加或减少引用计数,当引用计数减少到0时,智能指针会自动销毁所管理的对象。
不同类型的智能指针实现方式有所不同,例如std::unique_ptr使用独占语义,禁止复制和共享,因此没有引用计数的实现。而std::shared_ptr使用共享语义,需要引用计数来实现多个智能指针共享同一份资源。
参考文章
RALL 与 智能指针-CSDN博客