Hung-Chi's Blog on github

Design Pattern - Observer Pattern in C++ and Lua





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--" );
    
    product.attach( &shop1 );
    product.attach( &shop2 );
    product.setState( 12 );
    cout<< shop1.getName() << shop1.getState() <<endl;
    cout<< shop2.getName() << shop2.getState() <<endl;
    
    product.detach( &shop2 );
    product.setState( 11 );
    cout<< shop1.getName() << shop1.getState() <<endl;
    cout<< shop2.getName() << shop2.getState() <<endl;
    
    return 0;
}

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


Similar Posts


Comments


Advertisement