--- trunk/tengDissertation/Appendix.tex 2006/06/07 19:51:57 2816 +++ trunk/tengDissertation/Appendix.tex 2006/06/08 06:39:37 2821 @@ -118,25 +118,158 @@ The Singleton pattern ensures that only one instance o OOPSE}. \subsection{\label{appendixSection:singleton}Singleton} -The Singleton pattern ensures that only one instance of a class is -created. All objects that use an instance of that class use the same -instance. +The Singleton pattern not only provides a mechanism to restrict +instantiation of a class to one object, but also provides a global +point of access to the object. Currently implemented as a global +variable, the logging utility which reports error and warning +messages to the console in {\sc OOPSE} is a good candidate for +applying the Singleton pattern to avoid the global namespace +pollution.Although the singleton pattern can be implemented in +various ways to account for different aspects of the software +designs, such as lifespan control \textit{etc}, we only use the +static data approach in {\sc OOPSE}. {\tt IntegratorFactory} class +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_; + }; +\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}] + +IntegratorFactory::instance_ = NULL; + +IntegratorFactory* getInstance() { + if (instance_ == NULL){ + instance_ = new IntegratorFactory; + } + return instance_; +} +\end{lstlisting} +Since constructor is declared as {\tt protected}, a client can not +instantiate {\tt IntegratorFactory} directly. Moreover, since the +member function {\tt getInstance} serves as the only entry of access +to {\tt IntegratorFactory}, this approach fulfills the basic +requirement, a single instance. Another consequence of this approach +is the automatic destruction since static data are destroyed upon +program termination. + \subsection{\label{appendixSection:factoryMethod}Factory Method} -The Factory Method pattern is a creational pattern which deals with -the problem of creating objects without specifying the exact class -of object that will be created. Factory Method solves this problem -by defining a separate method for creating the objects, which -subclasses can then override to specify the derived type of product -that will be created. + +Categoried as a creational pattern, the Factory Method pattern deals +with the problem of creating objects without specifying the exact +class of object that will be created. Factory Method is typically +implemented by delegating the creation operation to the subclasses. +\begin{lstlisting}[float,caption={[].},label={appendixScheme:factoryDeclaration}] + class IntegratorCreator; + class IntegratorFactory { + public: + typedef std::map CreatorMapType; + + /** + * Registers a creator with a type identifier + * @return true if registration is successful, otherwise return false + * @id the identification of the concrete object + * @creator the object responsible to create the concrete object + */ + bool registerIntegrator(IntegratorCreator* creator); + + /** + * Looks up the type identifier in the internal map. If it is found, it invokes the + * corresponding creator for the type identifier and returns its result. + * @return a pointer of the concrete object, return NULL if no creator is registed for + * creating this concrete object + * @param id the identification of the concrete object + */ + 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; + } + Integrator* IntegratorFactory::createIntegrator(const std::string& id, SimInfo* info) { + CreatorMapType::iterator i = creatorMap_.find(id); + if (i != creatorMap_.end()) { + //invoke functor to create object + return (i->second)->create(info); + } else { + return NULL; + } + } +\end{lstlisting} + +\begin{lstlisting}[float,caption={[].},label={appendixScheme:integratorCreator}] + + class IntegratorCreator { + public: + IntegratorCreator(const std::string& ident) : ident_(ident) {} + virtual ~IntegratorCreator() {} + const std::string& getIdent() const { return ident_; } + + virtual Integrator* create(SimInfo* info) const = 0; + + private: + std::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);} + }; +\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 classes of the elements -that you are operating on. +structure without the need of changing the class heirarchy of the +elements that you are operating on. +\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); + }; +\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);} + }; + + 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 @@ -502,10 +635,10 @@ Dump2XYZ can transform an OOPSE dump file into a xyz f \subsection{\label{appendixSection:Dump2XYZ}Dump2XYZ} -Dump2XYZ can transform an OOPSE dump file into a xyz file which can -be opened by other molecular dynamics viewers such as Jmol and -VMD\cite{Humphrey1996}. The options available for Dump2XYZ are as -follows: +{\tt Dump2XYZ} can transform an OOPSE dump file into a xyz file +which can be opened by other molecular dynamics viewers such as Jmol +and VMD\cite{Humphrey1996}. The options available for Dump2XYZ are +as follows: \begin{longtable}[c]{|EFG|} @@ -536,7 +669,12 @@ The options available for Hydro are as follows: \end{longtable} \subsection{\label{appendixSection:hydrodynamics}Hydro} -The options available for Hydro are as follows: + +{\tt Hydro} can calculate resistance and diffusion tensors at the +center of resistance. Both tensors at the center of diffusion can +also be reported from the program, as well as the coordinates for +the beads which are used to approximate the arbitrary shapes. The +options available for Hydro are as follows: \begin{longtable}[c]{|EFG|} \caption{Hydrodynamics Command-line Options} \\ \hline