design pattern - observer pattern in c++ and lua
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
一一一一一一一一一一一一一一一一一一一一一一一一
© Hung-Chi's Blog
https://hungchicheng.github.io/2017/09/29/Design-Patterns-Observer-Pattern-in-lua-and-C++/
一一一一一一一一一一一一一一一一一一一一一一一一
What is Observer Pattern
Example in C++
#include <iostream>
#include <set>
using namespace std;
class Observer{
public:
virtual void update(int p) = 0;
};
class Subject{
protected:
std::set< Observer > m_observerList;
public:
void attach( Observer o ){ m_observerList.insert( o ); };
void detach( Observer *o ){ m_observerList.erase( o ); };
virtual void notify () = 0;
};
class Subject1:public Subject{
private:
int m_state;
public:
void notify (){
for ( auto &o : m_observerList ){
o->update(m_state);
}
};
void setState( int s ){
m_state = s;
notify();
}
int getState(){ return m_state; }
};
class Observer1:public Observer{
string m_name;
int m_state;
public:
Observer1( string name ):m_name( name ){}
void update( int p ){ m_state = p; } // override
string getName(){ return m_name; }
int getState(){ return m_state; }
};
class Observer2:public Observer{
string m_name;
int m_state;
public:
Observer2( string name ):m_name( name ){}
void update( int p ){ m_state = p; } // override
string getName(){ return m_name; }
int getState(){ return m_state; }
};
int main(int argc, char* argv[])
{
Subject1 product;
Observer1 shop1( "shop1–" );
Observer2 shop2( "shop2–" );
<span class="n">product</span><span class="p">.</span><span class="n">attach</span><span class="p">(</span> <span class="o">&</span><span class="n">shop1</span> <span class="p">);</span>
<span class="n">product</span><span class="p">.</span><span class="n">attach</span><span class="p">(</span> <span class="o">&</span><span class="n">shop2</span> <span class="p">);</span>
<span class="n">product</span><span class="p">.</span><span class="n">setState</span><span class="p">(</span> <span class="mi">12</span> <span class="p">);</span>
<span class="n">cout</span><span class="o"><<</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o"><<</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o"><<</span><span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span><span class="o"><<</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o"><<</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o"><<</span><span class="n">endl</span><span class="p">;</span>
<span class="n">product</span><span class="p">.</span><span class="n">detach</span><span class="p">(</span> <span class="o">&</span><span class="n">shop2</span> <span class="p">);</span>
<span class="n">product</span><span class="p">.</span><span class="n">setState</span><span class="p">(</span> <span class="mi">11</span> <span class="p">);</span>
<span class="n">cout</span><span class="o"><<</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o"><<</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o"><<</span><span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span><span class="o"><<</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o"><<</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o"><<</span><span class="n">endl</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
}
Output:
shop1--12
shop2--12
shop1--11
shop2--12
Example in Lua
function FuncNew( obj ) -- for Inheritance
function obj:new( o )
o = o or {}
setmetatable( o, self )
self.__index = self
return o
end
return obj
end
Observer = {}
function Observer:create()
function self:update( p ) – virtual update
– do nothing
end
return FuncNew( Observer ):new()
end
Subject = {}
function Subject:create()
self.m_observerList = {}
function self:attach( observer )
table.insert( self.m_observerList, observer )
end
function self:detach( observer )
for k,v in pairs( self.m_observerList ) do
if v == observer then
table.remove( self.m_observerList, k )
end
end
end
function self:notify() – virtual notify
– do nothing
end
return FuncNew( Subject ):new()
end
Subject1 = Subject:create() – inheritance Subject
function Subject1:create()
local m_state = nil
function self:notify() – override notify
for k,v in pairs( self.m_observerList ) do
v:update( m_state )
end
end
function self:setState( s )
m_state = s
self:notify()
end
function self:getState( s )
return m_state
end
return FuncNew( Subject1 ):new()
end
Observer1 = Observer:create() – inheritance Subject
function Observer1:create( n )
local m_name = n
local m_state = nil
function self:update( p ) – override update
m_state = p
end
function self:getName()
return m_name
end
function self:getState()
return m_state
end
return FuncNew( Observer1 ):new()
end
Observer2 = Observer:create() – inheritance Subject
function Observer2:create( n )
local m_name = n
local m_state = nil
function self:update( p ) – override update
m_state = p
end
function self:getName()
return m_name
end
function self:getState()
return m_state
end
return FuncNew( Observer2 ):new()
end
------------------------------------------------------
local product = Subject1:create()
local shop1 = Observer1:create( "shop1–" )
local shop2 = Observer2:create( "shop2–" )
product:attach( shop1 )
product:attach( shop2 )
product:setState( 12 )
–print( shop1.m_state )
print( shop1:getName() … tostring( shop1:getState() ) )
print( shop2:getName() … tostring( shop2:getState() ) )
print( "" )
product:detach( shop2 )
product:setState( 11 )
print( shop1:getName() … tostring( shop1:getState() ) )
print( shop2:getName() … tostring( shop2:getState() ) )
Output:
shop1--12
shop2--12
shop1–11
shop2–12
[Finished in 0.0s]