--- trunk/tengDissertation/Appendix.tex 2006/06/08 07:27:56 2822 +++ trunk/tengDissertation/Appendix.tex 2006/06/08 21:14:26 2833 @@ -131,17 +131,19 @@ is declared as is declared as \begin{lstlisting}[float,caption={[A classic Singleton design pattern implementation(I)] Declaration of {\tt IntegratorFactory} class.},label={appendixScheme:singletonDeclaration}] - class IntegratorFactory { - public: - static IntegratorFactory* getInstance(); - protected: - IntegratorFactory(); - private: - static IntegratorFactory* instance_; - }; +class IntegratorFactory { +public: + static IntegratorFactory* + getInstance(); +protected: + IntegratorFactory(); +private: + static IntegratorFactory* instance_; +}; + \end{lstlisting} The corresponding implementation is -\begin{lstlisting}[float,caption={[A classic Singleton design pattern implementation(II)] Implementation of {\tt IntegratorFactory} class.},label={appendixScheme:singletonImplementation}] +\begin{lstlisting}[float,caption={[A classic implementation of Singleton design pattern (II)] Implementation of {\tt IntegratorFactory} class.},label={appendixScheme:singletonImplementation}] IntegratorFactory::instance_ = NULL; @@ -151,6 +153,7 @@ IntegratorFactory* getInstance() { } return instance_; } + \end{lstlisting} Since constructor is declared as {\tt protected}, a client can not instantiate {\tt IntegratorFactory} directly. Moreover, since the @@ -171,116 +174,133 @@ result. identifier in the internal map. If it is found, it invokes the corresponding creator for the type identifier and returns its result. -\begin{lstlisting}[float,caption={[].},label={appendixScheme:factoryDeclaration}] - class IntegratorCreator; - class IntegratorFactory { - public: - typedef std::map CreatorMapType; +\begin{lstlisting}[float,caption={[The implementation of Factory pattern (I)].},label={appendixScheme:factoryDeclaration}] - bool registerIntegrator(IntegratorCreator* creator); +class IntegratorFactory { +public: + typedef std::map CreatorMapType; - Integrator* createIntegrator(const std::string& id, SimInfo* info); - - private: - CreatorMapType creatorMap_; - }; -\end{lstlisting} - -\begin{lstlisting}[float,caption={[].},label={appendixScheme:factoryDeclarationImplementation}] - bool IntegratorFactory::unregisterIntegrator(const std::string& id) { - return creatorMap_.erase(id) == 1; + bool registerIntegrator(IntegratorCreator* creator) { + return creatorMap_.insert(creator->getIdent(), creator).second; } - Integrator* - IntegratorFactory::createIntegrator(const std::string& id, SimInfo* info) { + Integrator* createIntegrator(const string& id, SimInfo* info) { + Integrator* result = NULL; CreatorMapType::iterator i = creatorMap_.find(id); if (i != creatorMap_.end()) { - //invoke functor to create object - return (i->second)->create(info); - } else { - return NULL; + result = (i->second)->create(info); } + return result; } + +private: + CreatorMapType creatorMap_; +}; \end{lstlisting} +\begin{lstlisting}[float,caption={[The implementation of Factory pattern (III)]Souce code of creator classes.},label={appendixScheme:integratorCreator}] -\begin{lstlisting}[float,caption={[].},label={appendixScheme:integratorCreator}] +class IntegratorCreator { +public: + IntegratorCreator(const string& ident) : ident_(ident) {} - class IntegratorCreator { - public: - IntegratorCreator(const std::string& ident) : ident_(ident) {} + const string& getIdent() const { return ident_; } - const std::string& getIdent() const { return ident_; } - virtual Integrator* create(SimInfo* info) const = 0; - private: - std::string ident_; - }; +private: + string ident_; +}; - template - class IntegratorBuilder : public IntegratorCreator { - public: - IntegratorBuilder(const std::string& ident) : IntegratorCreator(ident) {} - virtual Integrator* create(SimInfo* info) const { - return new ConcreteIntegrator(info); - } - }; +template +class IntegratorBuilder : public IntegratorCreator { +public: + IntegratorBuilder(const string& ident) + : IntegratorCreator(ident) {} + virtual Integrator* create(SimInfo* info) const { + return new ConcreteIntegrator(info); + } +}; \end{lstlisting} \subsection{\label{appendixSection:visitorPattern}Visitor} The purpose of the Visitor Pattern is to encapsulate an operation -that you want to perform on the elements of a data structure. In -this way, you can change the operation being performed on a -structure without the need of changing the class heirarchy of the -elements that you are operating on. +that you want to perform on the elements. The operation being +performed on a structure can be switched without changing the +interfaces of the elements. In other words, one can add virtual +functions into a set of classes without modifying their interfaces. +The UML class diagram of Visitor patten is shown in +Fig.~\ref{appendixFig:visitorUML}. {\tt Dump2XYZ} program in +Sec.~\ref{appendixSection:Dump2XYZ} uses Visitor pattern +extensively. -\begin{lstlisting}[float,caption={[].},label={appendixScheme:visitor}] - class BaseVisitor{ - public: - virtual void visit(Atom* atom); - virtual void visit(DirectionalAtom* datom); - virtual void visit(RigidBody* rb); - }; +\begin{figure} +\centering +\includegraphics[width=\linewidth]{visitor.eps} +\caption[The architecture of {\sc OOPSE}] {Overview of the structure +of {\sc OOPSE}} \label{appendixFig:visitorUML} +\end{figure} + +\begin{lstlisting}[float,caption={[The implementation of Visitor pattern (I)]Source code of the visitor classes.},label={appendixScheme:visitor}] + +class BaseVisitor{ +public: + virtual void visit(Atom* atom); + virtual void visit(DirectionalAtom* datom); + virtual void visit(RigidBody* rb); +}; + \end{lstlisting} -\begin{lstlisting}[float,caption={[].},label={appendixScheme:element}] - class StuntDouble { - public: - virtual void accept(BaseVisitor* v) = 0; - }; - class Atom: public StuntDouble { - public: - virtual void accept{BaseVisitor* v*} {v->visit(this);} - }; +\begin{lstlisting}[float,caption={[The implementation of Visitor pattern (II)]Source code of the element classes.},label={appendixScheme:element}] - class DirectionalAtom: public Atom { - public: - virtual void accept{BaseVisitor* v*} {v->visit(this);} - }; +class StuntDouble { +public: + virtual void accept(BaseVisitor* v) = 0; +}; - class RigidBody: public StuntDouble { - public: - virtual void accept{BaseVisitor* v*} {v->visit(this);} - }; +class Atom: public StuntDouble { +public: + virtual void accept{BaseVisitor* v*} { + v->visit(this); + } +}; +class DirectionalAtom: public Atom { +public: + virtual void accept{BaseVisitor* v*} { + v->visit(this); + } +}; + +class RigidBody: public StuntDouble { +public: + virtual void accept{BaseVisitor* v*} { + v->visit(this); + } +}; + \end{lstlisting} + \section{\label{appendixSection:concepts}Concepts} OOPSE manipulates both traditional atoms as well as some objects that {\it behave like atoms}. These objects can be rigid collections of atoms or atoms which have orientational degrees of -freedom. Here is a diagram of the class heirarchy: - -%\begin{figure} -%\centering -%\includegraphics[width=3in]{heirarchy.eps} -%\caption[Class heirarchy for StuntDoubles in {\sc oopse}-3.0]{ \\ -%The class heirarchy of StuntDoubles in {\sc oopse}-3.0. The -%selection syntax allows the user to select any of the objects that -%are descended from a StuntDouble.} \label{oopseFig:heirarchy} -%\end{figure} - +freedom. A diagram of the class heirarchy is illustrated in +Fig.~\ref{oopseFig:heirarchy}. Every Molecule, Atom and +DirectionalAtom in {\sc OOPSE} have their own names which are +specified in the {\tt .md} file. In contrast, RigidBodies are +denoted by their membership and index inside a particular molecule: +[MoleculeName]\_RB\_[index] (the contents inside the brackets depend +on the specifics of the simulation). The names of rigid bodies are +generated automatically. For example, the name of the first rigid +body in a DMPC molecule is DMPC\_RB\_0. +\begin{figure} +\centering +\includegraphics[width=\linewidth]{heirarchy.eps} +\caption[Class heirarchy for ojects in {\sc OOPSE}]{ A diagram of +the class heirarchy. \begin{itemize} \item A {\bf StuntDouble} is {\it any} object that can be manipulated by the integrators and minimizers. @@ -289,14 +309,8 @@ DirectionalAtom}s which behaves as a single unit. \item A {\bf RigidBody} is a collection of {\bf Atom}s or {\bf DirectionalAtom}s which behaves as a single unit. \end{itemize} - -Every Molecule, Atom and DirectionalAtom in {\sc OOPSE} have their -own names which are specified in the {\tt .md} file. In contrast, -RigidBodies are denoted by their membership and index inside a -particular molecule: [MoleculeName]\_RB\_[index] (the contents -inside the brackets depend on the specifics of the simulation). The -names of rigid bodies are generated automatically. For example, the -name of the first rigid body in a DMPC molecule is DMPC\_RB\_0. +} \label{oopseFig:heirarchy} +\end{figure} \section{\label{appendixSection:syntax}Syntax of the Select Command}