Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class System {
- public:
- boost::shared_ptr< Subsystem > GetSubsystem( unsigned int index ) {
- assert( index < mSubsystems.size() );
- return mSubsystems[ index ];
- }
- void LogMessage( const std::string& message ) {
- std::cout << message << std::endl;
- }
- private:
- typedef std::vector< boost::shared_ptr< Subsystem > > SubsystemList;
- SubsystemList mSubsystems;
- };
- class Subsystem {
- public:
- Subsystem( System* pParentSystem )
- : mpParentSystem( pParentSystem ) {
- }
- ~Subsystem() {
- pParentSubsystem->LogMessage( "Destroying..." );
- // Destroy this subsystem: deallocate memory, release resource, etc.
- }
- /*
- Other stuff here
- */
- private:
- System * pParentSystem; // raw pointer to avoid cycles - can also use weak_ptrs
- };
- int main() {
- {
- boost::shared_ptr< Subsystem > pSomeSubsystem;
- {
- boost::shared_ptr< System > pSystem( new System );
- pSomeSubsystem = pSystem->GetSubsystem( /* some index */ );
- } // Our System would go out of scope and be destroyed here, but the Subsystem that pSomeSubsystem points to will not be destroyed.
- } // pSomeSubsystem would go out of scope here but wait a second, how are we going to log messages in Subsystem's destructor?! Its parent System is destroyed after all. BOOM!
- return 0;
- }
- #include <iostream>
- #include <string>
- #include <vector>
- #include <boost/shared_ptr.hpp>
- // Forward Declarations to allow friending
- class System;
- class ProxyableSubsystemBase;
- // Base defining the interface for Subsystems
- class SubsystemBase
- {
- public:
- // pure virtual functions
- virtual void DoSomething(void) = 0;
- virtual int GetSize(void) = 0;
- virtual ~SubsystemBase() {} // virtual destructor for base class
- };
- // Null Object Pattern: an object which implements the interface to do nothing.
- class NullSubsystem : public SubsystemBase
- {
- public:
- // implements pure virtual functions from SubsystemBase to do nothing.
- void DoSomething(void) { }
- int GetSize(void) { return -1; }
- // Singleton Pattern: We only ever need one NullSubsystem, so we'll enforce that
- static NullSubsystem *instance()
- {
- static NullSubsystem singletonInstance;
- return &singletonInstance;
- }
- private:
- NullSubsystem() {} // private constructor to inforce Singleton Pattern
- };
- // Proxy Pattern: An object that takes the place of another to provide better
- // control over the uses of that object
- class SubsystemProxy : public SubsystemBase
- {
- friend class ProxyableSubsystemBase;
- public:
- SubsystemProxy(SubsystemBase *ProxiedSubsystem)
- : mProxied(ProxiedSubsystem)
- {
- }
- // implements pure virtual functions from SubsystemBase to forward to mProxied
- void DoSomething(void) { mProxied->DoSomething(); }
- int GetSize(void) { return mProxied->GetSize(); }
- protected:
- // State Pattern: the initial state of the SubsystemProxy is to point to a
- // valid SubsytemBase, which is passed into the constructor. Calling Nullify()
- // causes a change in the internal state to point to a NullSubsystem, which allows
- // the proxy to still perform correctly, despite the Subsystem going out of scope.
- void Nullify()
- {
- mProxied=NullSubsystem::instance();
- }
- private:
- SubsystemBase *mProxied;
- };
- // A Base for real Subsystems to add the Proxying behavior
- class ProxyableSubsystemBase : public SubsystemBase
- {
- friend class System; // Allow system to call our GetProxy() method.
- public:
- ProxyableSubsystemBase()
- : mProxy(new SubsystemProxy(this)) // create our proxy object
- {
- }
- ~ProxyableSubsystemBase()
- {
- mProxy->Nullify(); // inform our proxy object we are going away
- }
- protected:
- boost::shared_ptr<SubsystemProxy> GetProxy() { return mProxy; }
- private:
- boost::shared_ptr<SubsystemProxy> mProxy;
- };
- // the managing system
- class System
- {
- public:
- typedef boost::shared_ptr< SubsystemProxy > SubsystemHandle;
- typedef boost::shared_ptr< ProxyableSubsystemBase > SubsystemPtr;
- SubsystemHandle GetSubsystem( unsigned int index )
- {
- assert( index < mSubsystems.size() );
- return mSubsystems[ index ]->GetProxy();
- }
- void LogMessage( const std::string& message )
- {
- std::cout << " <System>: " << message << std::endl;
- }
- int AddSubsystem( ProxyableSubsystemBase *pSubsystem )
- {
- LogMessage("Adding Subsystem:");
- mSubsystems.push_back(SubsystemPtr(pSubsystem));
- return mSubsystems.size()-1;
- }
- System()
- {
- LogMessage("System is constructing.");
- }
- ~System()
- {
- LogMessage("System is going out of scope.");
- }
- private:
- // have to hold base pointers
- typedef std::vector< boost::shared_ptr<ProxyableSubsystemBase> > SubsystemList;
- SubsystemList mSubsystems;
- };
- // the actual Subsystem
- class Subsystem : public ProxyableSubsystemBase
- {
- public:
- Subsystem( System* pParentSystem, const std::string ID )
- : mParentSystem( pParentSystem )
- , mID(ID)
- {
- mParentSystem->LogMessage( "Creating... "+mID );
- }
- ~Subsystem()
- {
- mParentSystem->LogMessage( "Destroying... "+mID );
- }
- // implements pure virtual functions from SubsystemBase
- void DoSomething(void) { mParentSystem->LogMessage( mID + " is DoingSomething (tm)."); }
- int GetSize(void) { return sizeof(Subsystem); }
- private:
- System * mParentSystem; // raw pointer to avoid cycles - can also use weak_ptrs
- std::string mID;
- };
- //////////////////////////////////////////////////////////////////
- // Actual Use Example
- int main(int argc, char* argv[])
- {
- std::cout << "main(): Creating Handles H1 and H2 for Subsystems. " << std::endl;
- System::SubsystemHandle H1;
- System::SubsystemHandle H2;
- std::cout << "-------------------------------------------" << std::endl;
- {
- std::cout << " main(): Begin scope for System." << std::endl;
- System mySystem;
- int FrankIndex = mySystem.AddSubsystem(new Subsystem(&mySystem, "Frank"));
- int ErnestIndex = mySystem.AddSubsystem(new Subsystem(&mySystem, "Ernest"));
- std::cout << " main(): Assigning Subsystems to H1 and H2." << std::endl;
- H1=mySystem.GetSubsystem(FrankIndex);
- H2=mySystem.GetSubsystem(ErnestIndex);
- std::cout << " main(): Doing something on H1 and H2." << std::endl;
- H1->DoSomething();
- H2->DoSomething();
- std::cout << " main(): Leaving scope for System." << std::endl;
- }
- std::cout << "-------------------------------------------" << std::endl;
- std::cout << "main(): Doing something on H1 and H2. (outside System Scope.) " << std::endl;
- H1->DoSomething();
- H2->DoSomething();
- std::cout << "main(): No errors from using handles to out of scope Subsystems because of Proxy to Null Object." << std::endl;
- return 0;
- }
- main(): Creating Handles H1 and H2 for Subsystems.
- -------------------------------------------
- main(): Begin scope for System.
- <System>: System is constructing.
- <System>: Creating... Frank
- <System>: Adding Subsystem:
- <System>: Creating... Ernest
- <System>: Adding Subsystem:
- main(): Assigning Subsystems to H1 and H2.
- main(): Doing something on H1 and H2.
- <System>: Frank is DoingSomething (tm).
- <System>: Ernest is DoingSomething (tm).
- main(): Leaving scope for System.
- <System>: System is going out of scope.
- <System>: Destroying... Frank
- <System>: Destroying... Ernest
- -------------------------------------------
- main(): Doing something on H1 and H2. (outside System Scope.)
- main(): No errors from using handles to out of scope Subsystems because of Proxy to Null Object.
- class Subsystem
- {
- ...
- ~Subsystem() {
- boost::shared_ptr<System> my_system(pParentSystem.lock());
- if (NULL != my_system.get()) { // only works if pParentSystem refers to a valid System object
- // now you are guaranteed this will work, since a reference is held to the System object
- my_system->LogMessage( "Destroying..." );
- }
- // Destroy this subsystem: deallocate memory, release resource, etc.
- // when my_system goes out of scope, this may cause the associated System object to be destroyed as well (if it holds the last reference)
- }
- ...
- };
Add Comment
Please, Sign In to add comment