Game Development Reference
In-Depth Information
{
static_cast<OpenChestOption*>(m_openSwordChest.get())->SetChest(&m_swordChest);
m_enemies.emplace_back(CreateEnemy(EnemyType::Dragon));
static_cast<AttackEnemyOption*>(m_attackDragonOption.get())->SetEnemy(m_enemies[0]);
m_enemies.emplace_back(CreateEnemy(EnemyType::Orc));
static_cast<AttackEnemyOption*>(m_attackOrcOption.get())->SetEnemy(m_enemies[1]);
}
The constructor now calls the factory methods to create the proper instances needed to initialize the
shared_ptr for each Option and Enemy . Each Option has its own pointer, but the Enemy instances are
now placed into a vector using the emplace_back method. I've done this to show you how you can
use the shared_ptr::get method along with static_cast to convert the polymorphic base class to
the derived class needed to add the Enemy . The same type of cast is needed to add the address of
m_swordChest to the m_openSwordChest option.
That's all there is to creating basic factory functions in C++. These functions come into their own
when writing level loading code. Your data can store the type of object you'd like to create at any
given time and just pass it into a factory that knows how to instantiate the correct object. This
reduces the amount of code in your loading logic, which can help reduce bugs! This is definitely a
worthwhile goal.
Decoupling with the Observer Pattern
The observer pattern is very useful in decoupling your code. Coupled code is code that shares too
much information about itself with other classes. This could be specific methods in its interface or
variables that are exposed between classes. Coupling has a couple of major drawbacks. The first
is that it increases the number of places where your code must be updated when making changes
to exposed methods or functions and the second is that your code becomes much less reusable.
Coupled code is less reusable because you have to take over any coupled and dependent classes
when deciding to reuse just a single class.
Observers help with decoupling by providing an interface for classes to derive which provide
event methods that will be called on objects when certain changes happen on another class. The
Event system introduced earlier had an informal version of the observer pattern. The Event class
maintained a list of listeners that had their HandleEvent method called whenever an event they were
listening for was triggered. The observer pattern formalizes this concept into a Notifier template
class and interfaces that can be used to create observer classes. Listing 23-6 shows the code for
the Notifier class.
Listing 23-6. The Notifier Template Class
template <typename Observer>
class Notifier
{
private:
using Observers = std::vector<Observer*>;
Observers m_observers;
 
Search WWH ::




Custom Search