Observer Pattern Wiki

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">&amp;</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">&amp;</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">&lt;&lt;</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span><span class="o">&lt;&lt;</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o">&lt;&lt;</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">&amp;</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">&lt;&lt;</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">shop1</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span><span class="o">&lt;&lt;</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">shop2</span><span class="p">.</span><span class="n">getState</span><span class="p">()</span> <span class="o">&lt;&lt;</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

Download - Source Code


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]

Download - Source Code