CIS-255 Home http://www.c-jump.com/bcc/c255c/c255syllabus.htm

Object-oriented design patterns


  1. Object-oriented design
  2. Goals of object-oriented design
  3. Kinds of coupling
  4. Keeping coupling loose
  5. OO design patterns
  6. Patterns you've already seen
  7. Creation patterns
  8. Pattern One: Singleton
  9. Implementing singletons
  10. Extending Singleton
  11. Extended singleton code
  12. Disabling copy operations
  13. Disabling copy solution
  14. Disabling copy example
  15. Pattern Two: Prototype
  16. Implementing prototypes
  17. Covariant virtual functions
  18. Pattern Three: Adapter
  19. Implementing adapters
  20. Abstract adapter
  21. Pattern Four: Memento
  22. Implementing mementos

1. Object-oriented design



2. Goals of object-oriented design


  1. Maintainability

  2. Extensibility

  3. Reuse

     



3. Kinds of coupling



4. Keeping coupling loose



5. OO design patterns



6. Patterns you've already seen



7. Creation patterns



8. Pattern One: Singleton



9. Implementing singletons

  • 
    class Singleton {
    public:
        static Singleton* get_singleton();
        //...
    
    protected:
        Singleton();
    
    private:
        static Singleton* m_ptr;
    };// class Singleton
    
    Singleton* Singleton::m_ptr = NULL;
    
    Singleton* Singleton::get_singleton()
    {
        if ( m_ptr == NULL )
            m_ptr = new Singleton;
        return m_ptr;
    }
    
    
  • Singleton details:

    • Constructor is protected to prevent multiple instances.

    • Lazy creation avoids two problems with initialization:

      1. Unknown order of get_singleton( ) calls

      2. Might need some run-time information for proper initialization.

  • What if we also need to control deallocation?

10. Extending Singleton



11. Extended singleton code

  • 
    class Singleton {
    public:
        static Singleton* get_singleton();
    
    protected:
        static void register_instance( string name, Singleton* ptr );
        Singleton();
    
    private:
        static Singleton* m_ptr;
        static map< string, Singleton* > m_registry;
    
    };//class Singleton
    
    Singleton* Singleton::m_ptr = NULL;
    
    Singleton* Singleton::get_singleton()
    {
        if ( m_ptr == NULL ) {
            string name = getenv( "SINGLETON" );
            m_ptr = m_registry[ name ];
        }
        return m_ptr;
    }
    
    void Singleton::register_instance( string name, Singleton* ptr )
    {
        m_registry[name] = ptr;
    }
    
    
  • Subclasses must register themselves with the base class.

  • Might do this using constructor for new class together with single static object.

  • This does introduce possible startup sequence problems if using multiple compilation units.

  • To avoid this, one needs an explicit switch in get_singleton( ), but still no new client code.

12. Disabling copy operations



13. Disabling copy solution



14. Disabling copy example



15. Pattern Two: Prototype



16. Implementing prototypes

  • 
    class AbstractItem {
    public:
        virtual AbstractItem* clone() = 0;
        //...
    
    };//class AbstractItem
    
    class RealItemA : public AbstractItem
    {
    public:
        virtual AbstractItem* clone();
        //...
    
    };//class RealItemA
    
    class RealItemB : public AbstractItem
    {
    public:
        virtual AbstractItem* clone();
        //...
    
    };//class RealItemB
    
    
  • Prototype details:

    • Provides mechanism for virtual construction.

    • Instantiation of prototypes is deferred:

      • new prototypes can be instantiated dynamically at runtime

      • it is possible to delete existing prototypes.

  • We might also consider maintaining a registry of prototypes:

    
        std::map< std::string, AbstractItem* > item_registry;
    
    

17. Covariant virtual functions



18. Pattern Three: Adapter



19. Implementing adapters



20. Abstract adapter



21. Pattern Four: Memento



22. Implementing mementos

  • 
    class Memento {
    public:
        virtual ~Memento();
    
    private:
        friend class Item;
        Memento();
        //...
    };//class Memento
    
    class Item {
    public:
        Memento* create_memento();
        void restore_memento( Memento* );
        //...
    };//class Item
    
    
  • class Item is the originator with some internal states.

  • The user of Item::create_memento( ) and Item::restore_memento( ) is commonly referred to as a caretaker.

  • We usually want Memento objects be created only by Item::create_memento( ).

  • We might also want to allow incremental restoration via a stack of Mementos.

  • It is possible to implement Memento file I/O (or database) interface to add persistence of states.