Berard, Edward. Essays on Object-Oriented Software Engineering Vol 1, Prentice-Hall, 1993, chapter 6
Johnson, Ralph and Zweig, Jonathan, "Delegation in C++", Journal of Object-Oriented Programming, November/December 1991, pp 31-34
Gamma, Helm, Johnson, Vlissides Designs Patterns: Elements of Reusable Object-Oriented Software, Addision-Wesley, 1995
Parnas, D. L., "On the Criteria To Be Used in Decomposing Systems into Modules," Communications of the ACM, Vol. 5, No. 12, December 1972, pp. 1053-1058.
"Extracting the essential details about an item or group of items, while ignoring the unessential details."
"The process of identifying common patterns that have systematic variations; an abstraction represents the common pattern and provides a means for specifying which variation to use."
Abstraction can provide a different view of details
"The technique of encapsulating software design decisions in modules in such a way that the module's interface reveals as little as possible about the module's inner workings; thus each module is a "black box" to the other modules in the system"
Information hiding can be used to hide details of the procedural steps necessary to accomplish a task.
"We propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from others"
Abstraction is the purpose of hiding information
Enclosing all parts of an abstraction within a container
How one hides information
class SampleClassFormat { public: int PublicVariable; int PublicFunction(float argument); protected: int ProtectedVariable; int ProtectedFunction(float argument); private: int PrivateVariable; int PrivateFunction(float argument); static int OneCopy; }; int SampleClassFormat::OneCopy = 10; int SampleClassFormat::PublicFunction(float argument) { OneCopy = argument; return 5; };
"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice"
A pattern has four essential elements:
Modified OMT notation for classes and relationships
Notation - Relationships
Allow an object to alter its behavior when its internal state changes
TCPConnection object has different states:
Use the state pattern when:
class TCPState; class TCPConnection { public: TCPConnection(); ~TCPConnection(); int ActiveOpen(); int PassiveOpen(); int Close(); int Transmit(TCPMessage*); private: friend class TCPState; void ChangeState(TCPState*); private: TCPState* state; // other stuff not shown }; TCPConnection::TCPConnection() { state = TCPClosed::Instance(); } void TCPConnection::ChangeState(TCPState* newState) { state = newState; } int TCPConnection::ActiveOpen() { return state->ActiveOpen(this); } class TCPState { public: virtual int ActiveOpen( TCPConnection* ); virtual int PassiveOpen( TCPConnection* ); virtual int Close( TCPConnection* ); virtual int Transmit( TCPConnection*, TCPMessage*); protected: void ChangeState(TCPConnection*, TCPState*); }; //Default behavior for all requests int TCPState :: ActiveOpen( TCPConnection* ) { }; int TCPState :: PassiveOpen( TCPConnection* ) { }; int TCPState :: Close( TCPConnection* ) { }; int Transmit( TCPConnection*, TCPMessage*) { }; void TCPState :: ChangeState(TCPConnection* connection, TCPState * newState) { connection -> ChangeState(newState); } class TCPClosed : public TCPState { public: static TCPState* Instance(); virtual int ActiveOpen( TCPConnection* ); virtual int PassiveOpen( TCPConnection* ); virtual int Close( TCPConnection* ); // etc. }; int TCPClosed :: ActiveOpen( TCPConnection* connection) { // do the actual work to open an active socket here ChangeState(connection, TCPEstablished::Instance()); }
state Input A Input B Input C state 1 state 3 state 2 state 1 state 2 state 2 state 1 state 3 state 3 state 1 state 2 state 1
Ensure a class has only one instance
Provide a global point of access to the single instance
Use this pattern when:
class Singleton { public: static Singleton* Instance(); protected: Singleton(); private: static Singleton* _instance; }; Singleton* Singleton :: _instance = 0; Singleton* Singleton :: Instance () { if ( _instance == 0) _instance = New Singleton; return _instance ; }
class Singleton { public: static void Register(char* name, Singleton*); static Singleton* Instance(char* name); protected: static Singleton* Lookup(const char* name); private: static Singleton* _instance; static List<NameSingletonPair>* _registry; }; Singleton* Singleton :: _instance = 0; Singleton* Singleton :: Instance (char* name) { if ( _instance == 0) { _instance = Lookup( name ); //Returns 0 if no such instance } return _instance ; }
class FooSingleton : public Singleton { public: FooSingleton(); } FooSingleton :: FooSingleton() { Singleton :: Register("FooSingleton", this ); } // in implementation file static FooSingleton barSingleton;