-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
712 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
CC=g++ | ||
CFLAGS= -c -Wall -ansi -pedantic | ||
LDFLAGS= | ||
SOURCES= src/main.cpp src/sword.cpp src/shuriken.cpp src/samurai.cpp src/factory.cpp | ||
OBJECTS=$(SOURCES:.cpp=.o) | ||
EXECUTABLE=samurai | ||
LIBS= -lboost_thread | ||
|
||
all: $(SOURCES) $(EXECUTABLE) | ||
|
||
$(EXECUTABLE): $(OBJECTS) | ||
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o bin/$@ | ||
|
||
.cpp.o: | ||
$(CC) $(CFLAGS) $< -o $@ | ||
|
||
clean: | ||
rm -f src/*.o bin/$(EXECUTABLE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
#ifndef BASEIOC_H | ||
#define BASEIOC_H | ||
|
||
#include <stdlib.h> | ||
#include <sstream> | ||
#include <map> | ||
#include <typeinfo> | ||
#include <iostream> | ||
#include <stdexcept> | ||
#include <string> | ||
#include <stdarg.h> | ||
|
||
#include "singleton.h" | ||
|
||
namespace DiLite | ||
{ | ||
/** | ||
Template used to create instance of specific type T. | ||
@return Void pointer to object instance. | ||
*/ | ||
template<typename T> void* CreateInstance() { return new T; } | ||
|
||
/** | ||
The Dependency Injection (DI) container class. | ||
@author SW801 | ||
*/ | ||
class BaseDI | ||
{ | ||
private: | ||
/** A map of <TypeId, function pointer> to create object instances */ | ||
std::map<std::string, void*(*)()> _objectConstructors; | ||
|
||
/** A map of <TypeId, void pointer> to refer to singleton instances */ | ||
std::map<std::string, void*> _singletons; | ||
|
||
/** | ||
Checks if an object constructor or singleton of type I has been registered. | ||
*/ | ||
template<typename I> void CheckExistence() | ||
{ | ||
if(_singletons.find(typeid(I).name()) != _singletons.end() || _objectConstructors.find(typeid(I).name()) != _objectConstructors.end()) | ||
throw std::runtime_error(((std::string) typeid(I).name()) + " is already bound."); | ||
} | ||
|
||
/** | ||
Type parameter constraint: checks that T is derived from B | ||
Courtesy of: Bjarne Stroustrup, | ||
http://www2.research.att.com/~bs/bs_faq2.html#constraints | ||
*/ | ||
template<class T, class B> struct Derived_from | ||
{ | ||
static void constraints(T* p) | ||
{ | ||
B* pb = p; | ||
} | ||
Derived_from() | ||
{ | ||
void(*p)(T*) = constraints; | ||
} | ||
}; | ||
|
||
public: | ||
/** | ||
Bind type I in transient scope using construction function. | ||
Each time resolved, a new instance is created and returned. | ||
@param pt2func Function pointer to construction function. | ||
*/ | ||
template<typename I> void Bind(I*(*pt2func)()) | ||
{ | ||
CheckExistence<I>(); | ||
_objectConstructors[typeid(I).name()] = (void*(*)())pt2func; | ||
} | ||
|
||
/** | ||
Bind type I to type T in transient scope using default constructor of T. | ||
Each time resolved, a new instance is created and returned. | ||
*/ | ||
template<typename I, typename T> void Bind() | ||
{ | ||
Derived_from<T,I>(); | ||
CheckExistence<I>(); | ||
_objectConstructors[typeid(I).name()] = &CreateInstance<T>; | ||
} | ||
|
||
/** | ||
Bind type I to type T in singleton scope using default constructor of T. | ||
Each time resolved, the same instance is returned. | ||
*/ | ||
template<typename I, typename T> void BindSingle() | ||
{ | ||
Derived_from<T,I>(); | ||
CheckExistence<I>(); | ||
_singletons[typeid(I).name()] = &Singleton<T>::GetInstance(); | ||
} | ||
|
||
/** | ||
Bind type I to type T in singleton scope using construction function. | ||
Each time resolved, the same instance is returned. | ||
@param pt2func Function pointer to construction function. | ||
*/ | ||
template<typename I, typename T> void BindSingle(I*(*pt2func)()) | ||
{ | ||
Derived_from<T,I>(); | ||
CheckExistence<I>(); | ||
_singletons[typeid(I).name()] = &Singleton<T>::CreateInstance((void*(*)())pt2func); | ||
} | ||
|
||
/** | ||
Resolve an instance of the desired type/interface. | ||
Object may be pre-existing if registered as singleton. | ||
Otherwise lazily constructed using an object constructor. | ||
*/ | ||
template<typename I> I* Resolve() | ||
{ | ||
// Check if "resolvable" from singleton scope | ||
if(_singletons.find(typeid(I).name()) != _singletons.end()) | ||
return ((I*)_singletons[typeid(I).name()]); | ||
|
||
// Check if "resolvable" from transient scope | ||
if(_objectConstructors.find(typeid(I).name()) != _objectConstructors.end()) | ||
return ((I*)_objectConstructors[typeid(I).name()]()); | ||
|
||
// Binding not found | ||
throw std::runtime_error(((std::string) typeid(I).name()) + " is not bound."); | ||
} | ||
|
||
/** | ||
Unbinds every registered object constructor and singleton instance. | ||
*/ | ||
template<typename I> void Unbind() | ||
{ | ||
// Unbind all objects in transient scope | ||
std::map<std::string, void*(*)()>::iterator it_transients = _objectConstructors.find(typeid(I).name()); | ||
|
||
if (it_transients != _objectConstructors.end()) | ||
{ | ||
_objectConstructors.erase(it_transients); | ||
} | ||
|
||
// Unbind all objects in singleton scope | ||
std::map<std::string, void*>::iterator it_singletons = _singletons.find(typeid(I).name()); | ||
|
||
if (it_singletons != _singletons.end()) | ||
{ | ||
_singletons.erase(it_singletons); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
Typedefinition of the Singleton DI container. | ||
*/ | ||
typedef Singleton<BaseDI> DI; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#ifndef SINGLETON_H_SW8 | ||
#define SINGLETON_H_SW8 | ||
|
||
#include <cassert> | ||
#include <boost/thread/mutex.hpp> | ||
|
||
namespace DiLite | ||
{ | ||
/** | ||
Template for any class that should be in | ||
singleton scope. | ||
*/ | ||
template<typename T> class Singleton | ||
{ | ||
private: | ||
/** Indicates if the singleton has been destructed */ | ||
static bool _isDestructed; | ||
|
||
/** The mutex used by the singleton to enable thread-safety */ | ||
static boost::mutex& GetMutex() | ||
{ | ||
static boost::mutex mutex; | ||
return mutex; | ||
} | ||
|
||
/** Prevent construction of Singleton class */ | ||
Singleton() {} | ||
|
||
/** Prevent destruction of Singleton class */ | ||
~Singleton() { _isDestructed = true; } | ||
|
||
/** Prevent copy of Singleton */ | ||
Singleton(Singleton const&); | ||
|
||
/** Prevent assignment to Singleton */ | ||
void operator=(Singleton const&); | ||
|
||
public: | ||
/** | ||
Gets the instance wrapped by the Singleton. | ||
@return A singleton object of type T. | ||
*/ | ||
static T& GetInstance() | ||
{ | ||
assert(!_isDestructed); | ||
boost::mutex::scoped_lock lock(GetMutex()); | ||
static T instance; | ||
return instance; | ||
} | ||
|
||
/** | ||
Creates and gets an instance of type T in singleton scope. | ||
@param ctor A function pointer to a construction function returning T. | ||
@return A singleton object of type T. | ||
*/ | ||
static T& CreateInstance(void*(*ctor)()) | ||
{ | ||
assert(!_isDestructed); | ||
boost::mutex::scoped_lock lock(GetMutex()); | ||
static T instance = *((T*)ctor()); | ||
return instance; | ||
} | ||
}; | ||
|
||
/** | ||
Force creation of the mutex before main() is called. | ||
This happens as a consequence of the comma-operator and semantics of sequence points. | ||
*/ | ||
template<typename T> bool Singleton<T>::_isDestructed = (Singleton<T>::GetMutex(), false); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#include "factory.h" | ||
#include "i_weapon.h" | ||
#include "samurai.h" | ||
|
||
namespace SampleCode | ||
{ | ||
IWarrior* Factory::CreateSamurai() | ||
{ | ||
return new Samurai(DiLite::DI::GetInstance().Resolve<IWeapon>()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#ifndef FACTORY_H | ||
#define FACTORY_H | ||
|
||
#include "dilite/di.h" | ||
#include "i_warrior.h" | ||
|
||
namespace SampleCode | ||
{ | ||
/** | ||
A factory class to instantiate objects in the program. | ||
Provides coupling between the running program and the | ||
DI framework. | ||
@author SW801 | ||
*/ | ||
class Factory | ||
{ | ||
public: | ||
/** | ||
Creates a new Samurai using the DI framework. | ||
@return IWarrior pointer to the Samurai object. | ||
*/ | ||
static IWarrior* CreateSamurai(); | ||
}; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#ifndef I_WARRIOR | ||
#define I_WARRIOR | ||
|
||
#include <string> | ||
|
||
namespace SampleCode | ||
{ | ||
/** | ||
Interface for warriors. | ||
*/ | ||
class IWarrior | ||
{ | ||
|
||
protected: | ||
/** The name of the warrior */ | ||
std::string _name; | ||
|
||
/** The remaining life of the warrior */ | ||
int _life; | ||
|
||
public: | ||
/** | ||
Constructor | ||
@param name The name of the warrior. | ||
@param life The initial life of the warrior. | ||
*/ | ||
IWarrior(const std::string& name, int life): _name(name), _life(life) {} | ||
|
||
/** | ||
Attacks an opponent. | ||
@param opponent The opponent to attack. | ||
*/ | ||
virtual void Attack(IWarrior* opponent) const = 0; | ||
|
||
/** | ||
Takes damage from an opponents hit. | ||
@param damage The damage to receive. | ||
*/ | ||
virtual void TakeDamage(int damage) = 0; | ||
|
||
/** | ||
Accessor function for the name. | ||
@post Does not change the object. | ||
@return Name of the warrior. | ||
*/ | ||
virtual std::string GetName() const = 0; | ||
|
||
/** | ||
Mutator function for the name. | ||
@param newName The new name for the warrior. | ||
*/ | ||
virtual void SetName(const std::string& newName) = 0; | ||
|
||
/** | ||
Accessor function for the alive property of the warrior. | ||
@post Does not change the object. | ||
@return True if alive. | ||
*/ | ||
virtual bool IsAlive() const = 0; | ||
|
||
/** | ||
Empty deconstructor. | ||
*/ | ||
virtual ~IWarrior() {} | ||
}; | ||
} | ||
|
||
#endif |
Oops, something went wrong.