I've read the decorator design pattern from Wikipedia, and code example from this site.
I see the point that traditional inheritance follows an 'is-a' pattern whereas decorator follows a 'has-a' pattern. And the calling convention of decorator looks like a 'skin' over 'skin' .. over 'core'. e.g.
I* anXYZ = new Z( new Y( new X( new A ) ) );
as demonstrated in above code example link.
However there are still a couple of questions that I do not understand:
what does wiki mean by 'The decorator pattern can be used to extend (decorate) the functionality of a certain object at run-time'? the 'new ...(new... (new...))' is a run-time call and is good but a 'AwithXYZ anXYZ;' is a inheritance at compile time and is bad?
from the code example link I can see that the number of class definition is almost the same in both implementations. I recall in some other design pattern books like 'Head first design patterns'. They use starbuzz coffee as example and say traditional inheritance will cause a 'class explosion' because for each combination of coffee, you would come up with a class for it.
But isn't it the same for decorator in this case? If a decorator class can take ANY abstract class and decorate it, then I guess it does prevent explosion, but from the code example, you have exact # of class definitions, no less...
Would anyone explain?
Let's take some abstract streams for example and imagine you want to provide encryption and compression services over them.
With decorator you have (pseudo code):
Stream plain = Stream();
Stream encrypted = EncryptedStream(Stream());
Stream zipped = ZippedStream(Stream());
Stream zippedEncrypted = ZippedStream(EncryptedStream(Stream());
Stream encryptedZipped = EncryptedStream(ZippedStream(Stream());
With inheritance, you have:
class Stream() {...}
class EncryptedStream() : Stream {...}
class ZippedStream() : Stream {...}
class ZippedEncryptedStream() : EncryptedStream {...}
class EncryptedZippedStream() : ZippedStream {...}
1) with decorator, you combine the functionality at runtime, depending on your needs. Each class only takes care of one facet of functionality (compression, encryption, ...)
2) in this simple example, we have 3 classes with decorators, and 5 with inheritance. Now let's add some more services, e.g. filtering and clipping. With decorator you need just 2 more classes to support all possible scenarios, e.g. filtering -> clipping -> compression -> encription.
With inheritance, you need to provide a class for each combination so you end up with tens of classes.
In reverse order:
2) With, say, 10 different independent extensions, any combination of which might be needed at run time, 10 decorator classes will do the job. To cover all possibilities by inheritance you'd need 1024 subclasses. And there'd be no way of getting around massive code redundancy.
1) Imagine you had those 1024 subclasses to choose from at run time. Try to sketch out the code that would be needed. Bear in mind that you might not be able to dictate the order in which options are picked or rejected. Also remember that you might have to use an instance for a while before extending it. Go ahead, try. Doing it with decorators is trivial by comparison.
You are correct that they can be very similar at times. The applicability and benefits of either solution will depend on your situation.
Others have beat me to adequate answers to your second question. In short it is that you can combine decorators to achieve more combinations which you cannot do with inheritance.
As such I focus on the first:
You cannot strictly say compile-time is bad and run-time is good, it is just different flexibility. The ability to change things at run-time can be important for some projects because it allows changes without recompilation which can be slow and requires you be in an environment where you can compile.
An example where you cannot use inheritance, is when you want to add functionality to an instantiated object. Suppose you are provided an instance of an object that implements a logging interface:
public interface ILog{
//Writes string to log
public void Write( string message );
}
Now suppose you begin a complicated task that involves many objects and each of them does logging so you pass along the logging object. However you want every message from the task to be prefixed with the task Name and Task Id. You could pass around a function, or pass along the Name and Id and trust every caller to follow the rule of pre-pending that information, or you could decorate the logging object before passing it along and not have to worry about the other objects doing it right
public class PrependLogDecorator : ILog{
ILog decorated;
public PrependLogDecorator( ILog toDecorate, string messagePrefix ){
this.decorated = toDecorate;
this.prefix = messagePrefix;
}
public void Write( string message ){
decorated.Write( prefix + message );
}
}
Sorry about the C# code but I think it will still communicate the ideas to someone who knows C++
To address the second part of your question (which might in turn address your first part), using the decorator method you have access to the same number of combinations, but don't have to write them. If you have 3 layers of decorators with 5 options at each level, you have 5*5*5 possible classes to define using inheritance. Using the decorator method you need 15.
First off, I'm a C# person and haven't dealt with C++ in a while, but hopefully you get where I'm coming from.
A good example that comes to mind is a DbRepository and a CachingDbRepository:
public interface IRepository {
object GetStuff();
}
public class DbRepository : IRepository {
public object GetStuff() {
//do something against the database
}
}
public class CachingDbRepository : IRepository {
public CachingDbRepository(IRepository repo){ }
public object GetStuff() {
//check the cache first
if(its_not_there) {
repo.GetStuff();
}
}
So, if I just used inheritance, I'd have a DbRepository and a CachingDbRepository. The DbRepository would query from a database; the CachingDbRepository would check its cache and if the data wasn't there, it would query a database. So there's a possible duplicate implementation here.
By using the decorator pattern, I still have the same number of classes, but my CachingDbRepository takes in a IRepository and calls its GetStuff() to get the data from the underlying repo if it's not in the cache.
So the number of classes are the same, but the use of the classes are related. CachingDbRepo calls the Repo that was passed into it...so it's more like composition over inheritance.
I find it subjective when to decide when to use just inheritance over decoration.
I hope this helps. Good luck!
Related
I have a question about design patterns. My project is starting to get bigger and bigger and I feel like my design pattern is inaccurate/imprecise in terms of maintainability, scalability, and readability. The way my project is currently structured is that I have a MainLoopFile where I poll my events, I handle the events, draw the textures, and most importantly, instanciate external classes such as MyClassA up to some arbitrary MyClassZ.
The issue is that I'm making only one instance of each of MyClassX, just so that I can access their member functions fooA(), fooB() using MyClassX x; x.fooA(); from with the main loop file.
Is this the best approach to do this? I feel like
Write a class
Make a instance of the class
Call the functions of that class
methodology is useful whenever one needs to make multiple instances of that class. In my case, I'm only making one. Here is an example
MyClassA.hpp
MyClassA {
fooA();
fooB();
};
MyClassB.hpp
MyClassB {
fooA();
fooB();
};
...
MyClassZ.hpp
MyClassZ {
fooA();
fooB();
};
MainLoopFile.cpp
#include "MyClassA.hpp"
#include "MyClassB.hpp"
...
#include "MyClassZ.hpp"
MainLoopFile {
MyClassA a;
MyClassB b;
...
MyClassZ z;
while() {
Event event;
// do operations on a,b,...,z
}
}
Is this design pattern correct? Is there anything better?
Things I have considered
Making namespaces although I don't understand if that is the correct solution
Making some of the classes static (since only one instance necessary), but then half of my project's content becomes static, and it just feels odd
Read online about some design patterns, but was not able to find an answer to this specific solution
The model you describe is called a 'singleton' and its a common design pattern. The debate as to whether 'raw code' not in any class , singleton or static methods of a class is a long running lively one.
A singleton is better if some point you might need 2. Now you simply have to create another one. If its all static you have a lot of rewriting to do.
The thing that encapsulates the start up logic 'MainFile' in your case clearly is best static, since you are only running one program.
Things that encapsulate objects that you operate on are probably best as singletons.
Advantage of statics is that they are always there, you dont have to hand pointer / references around. You can just say Froodle::Noodle(widget) and there you are. The down side of that though is its a huge reorg if suddenly you need 2 Froodles
Just so I understand what you're doing -- you're using MyClassA .. Z in order to organize your code. That seems reasonable. But you don't actually have data associated with them.
The two most obvious answers, if I understand your problem correctly, could be:
Use namespaces and free functions within the namespaces
Use static methods so at least you're not instantiating empty objects
For the latter, you could then just call MyClassA::foo(); without having an instance of MyClassA.
To ask a design question, the most important part is that "what you want to achieve and what's the limitation" instead of "what you've done" (unless you're facing a legacy codebase, then current architecture is the limitation).
Please explain the context what class A ~ Z does.
Are they holding states or just having the same function names?
Why do you need so many different flavors of the same function name?
You may combine multiple patterns to achieve what you want to do.
By your sample code, I presume you want an event loop system (event loop is a design pattern as well!).
You may have multiple event handler instances. Making them Singleton might be what you want, but I don't suggest to make them singleton if your instances have dependency on other instances
To handle event, I think Observer Pattern is too big for this case. I'd suggest to use Strategy Pattern here since you might want to use different handlers according to different event types.
this is my first post and I really did a lot of research on the topic before posting here. But now I found several possible solutions and I'm just not sure what is the proper way.
Problem
We are currently developing a local coop game that is a mix of an action game for one player and a puzzle game for the second one. Our actual problem is the input that is currently handled by a player controller that casts on every action mapping delegate received to determine if the possessed Pawn is from type PlayerA or PlayerB to then call the right function.
Let me give you a specific example:
We have two action bindings for the Button B (XBox Controller) currently called "B"
When the delegate is called we cast the possessedPlayer to check whether it shall call PlayerA->Jump or PlayerB->Blink
I'm totally unhappy with the situation that I have to cast everytime we receive an Input just to check wether I have possessed action/puzzle char
Solutions
1) Create 2 PlayerControllers and swap them by using GameMode::SwapPlayerController(Old, New)
I found this function during research but I'm not happy with creating a Player with PlayerControllerA to immediately switch it to use PlayerControllerB,
2) Shift responsibility to the Charatcer class
Another thought would be to delegate the decision making to the Character class by passing down an enum value like E_BUTTON_B from the PlayerController to the Character. We could write a macro that creates this enum based on our input mappings and then delegate the decision to a generic Character->ProcessInput(EnumValue) function. I'm also not quite happy because then the PC does not make so much sense to me.
3) Cache the possessed Pawn to avoid the cast
Another idea would have been to cache the type of the possessed Character whenever the PC possesses a Pawn. This would get rid of the cast per input delegate call.
I would be very glad for advide and any hint how you folks solve such issues in your games. Our main goals are separation of concern, good maintainability and input rebinding.
Cheers and have a nice day,
Parzival
You can create structure like this (written in C++, but this approach could be easily implemented in Blueprints as well):
class MyGameBasePlayerController : public PlayerController
{
// TODO methods common for both controllers (for example Escape key handling)
}
Now specific controllers:
class PuzzlePlayerControler : public MyGameBasePlayerController
{
UPROPERTY(BlueprintReadWrite, Transient, Category = "MyCat"
PuzzleCharacter* puzzleChar;
// TODO handle specific actions for Puzzle chararacter and control handling.
// TODO override base methods / input bindings if necesary
virtual void Possess(APawn* pawn) override;
}
Same goes for ActionPlayerCharacter.
You need to decide, how your characters will differ. If they are same, you can use something like MyGameCharacter : public PlayerCharacter (or you can use broader class PlayerPawn) and your PlayerControllers will call appropriate methods. Then your stored reference to MyGameCharacter can be stored in MyGameBasePlayerController.
Or you can use inheritance as well, so you will have PuzzleCharacter : public MyGameCharacter and ActionCharacter : MyGameCharacter with some common base implementation and extending methods or use virtual method overriding.
Depending on your final structure, you can use overriden Possess method (UE Docs) to get actual pawn instance, cast it to appropriate class (for example PuzzleCharacter or PuzlePawn in PuzzlePlayerController) and store reference for later usage. Be aware that in this case you should implement Unpossess as well, so you can clear your stored reference and behave correctly in any given situation.
I'm trying to design an API and I'm wondering which approach is better. I have this concept I'll call a Message. This Message is composed of up to five MessageElements. There are about 300 MessageElements the user can add to a Message.
There are two approaches that I've thought of so far on to model this in C++. One, I can have a Message class with a method to add each MessageElement:
class Message
{
public:
void AddMessageElement1();
void AddMessageElement2();
void AddMessageElement3();
...
void AddMessageElement300();
};
(Note: the MessageElements aren't actually called "MessageElement1", "MessageElement2", etc.. They actually have more descriptive names than that. I'm just being generic here.)
Or, I represent each MessageElement by a class that all derive from a MessageElement base class. The Message class would thus have a single "Add()" method like so:
class Message
{
public:
void Add(const MessageElement& element);
};
The advantage to approach 1 is that the class hierarchy is simple. I won't have 300+ classes in the library. Basically just one class. However, that'll be one class with 300+ methods. Plus, any changes to the class's public API (like I have to add an additional MessageElement type) would require a recompile of all users of the class.
The advantage to approach 2 is that the Message class's API becomes really simple. Also, adding additional MessageElement types would not require a recompile of all the users of the Message class. The disadvantage is that I'll have 300+ little classes populating the library's API.
Which approach would be better? I'm kind of leaning towards approach 2. But approach 1 seems easier for user's to grasp.
Go with approach number 2.
Besides the advantages you stated (simple API for Message and modularity), you will have much more testable code with this approach (usually testable code is manageable and reusable code).
Approach 1 creates a monster;
If I went to an interview and the interviewer told me "we have a class with 300 methods in our code base" I would seriously consider not working there at all.
With approach 2 you may be able to centralize some of the the code in MessageElement, into a base class (much more natural than centralizing element-speciffic code into the Message class).
I quite often find myself creating interfaces that I am using just at the signature to inject a dependency, ending up with class AIface and class AImpl : public AIface. And quite often I never implement any other subclass of class AIface
Is there any advantage of this approach vs using directly the implementation with all public method virtual?
Longer Explanation:
Say we have a zoo with a cleaning service. We do TDD, and we want to be able to test the Zoo with a fake FeedingSvc, so we go for dependency injecton.
What is the difference between:
class FeedingSvcIface{
virtual void performFeeding() = 0;
} ;
class RoboticFeedingSvc: public FeedingSvcIface{
void performFeeding();
};
Class Zoo{
Zoo(FeedingSvcIface&);
//...
};
vs
class RoboticFeedingSvc{
virtual void performFeeding();
};
Class Zoo{
Zoo(RoboticFeedingSvc&);
//...
};
(And if ever needed, extract the interface in the future)
In terms of testing, the former seems easier.
I usually find natural to add interfaces when there is a I speak to a class that "crosses layers" but some times it is just about testing.
I know that in the future I might have to implement other types of FeedingSvcs but why doing the abstraction today if I don't really needed?,
I might split two classes just to encapsulate some logic.
The advantage of sticking to best practices, design patterns or other idioms is that although you make a bit of extra effort now, you gain more in the long run.
Imagine the scenario where you work in a team, with multiple developers, some experienced, some not.
You are the creator of the Zoo mechanism, but you decide, that for the time being, you will implement the Zoo on a KISS principle without adding the extra abstraction . You set yourself a mental note (or a even a nice little comment) stating that "If there shall be multiple distinct behaviors of the RoboticFeedingSvc there shall be Abstraction over the dependency injection !".
Now , because of your really awesome work, you get to go on a vacation and some junior developer will remain to mantain your code.
One of the tasks of the developer will be to introduce a ManualFeeding option and a hybrid option. How many ways to do this can you think about (with disregards to any coding principle) ?
Because you, the creator, didn't enforce the way the mechanism grows, the junior developer will look at your comment, add a "LoL u mad bro :) " comment , and then choose one of the following :
Create a base interface to be derived by other FeedingSvcs (you got lucky here)
Create a dependency injection to the RobotFeedingSvc using a strategy pattern (have some functors to be set in terms of how to feed something)
Make RobotFeedingSvc a composite between Feeder, Feeded, and some Action function
Make the RobotFeedingSvc a singleton factory (because singletons factories are awesome and fancy ) that somehow is used inside the Zoo to return the apropriate feeding technique (important thing here is that he used singleton and factory)
Create a templated version of the Zoo that takes a templated version of RobotFeedingSvc that is partially sepecialized according to given FeedingPolicy and Feeder (because he just bumped into templates, and templates should be used everywhere).
I guess we could sum up the story in fewers lines :
Making the initial effort to properly make the abstractions layer required in your application to make it scalable in terms of functionality will help other developers (including here future you ) to quickly understand the proper way to implement new features using the existing code instead of just hacking through it with some wild ideas.
Forcing your Zoo Class to take an interface instead of a concrete class is pretty much equivalent to leave a comment saying that new functionalities need to implement this interface.
Allowing a concrete class to be passed as parameter might switch focus on how to change the concrete class rather then implement something on top of it.
Another more technical reason would be the following :
He needs to add new functionality , but he's not allowed to change the Zoo implementation. What now ?
I have a project with a large codebase (>200,000 lines of code) I maintain ("The core").
Currently, this core has a scripting engine that consists of hooks and a script manager class that calls all hooked functions (that registered via DLL) as they occur. To be quite honest I don't know how exactly it works, since the core is mostly undocumented and spans several years and a magnitude of developers (who are, of course, absent). An example of the current scripting engine is:
void OnMapLoad(uint32 MapID)
{
if (MapID == 1234)
{
printf("Map 1234 has been loaded");
}
}
void SetupOnMapLoad(ScriptMgr *mgr)
{
mgr->register_hook(HOOK_ON_MAP_LOAD, (void*)&OnMapLoad);
}
A supplemental file named setup.cpp calls SetupOnMapLoad with the core's ScriptMgr.
This method is not what I'm looking for. To me, the perfect scripting engine would be one that will allow me to override core class methods. I want to be able to create classes that inherit from core classes and extend on them, like so:
// In the core:
class Map
{
uint32 m_mapid;
void Load();
//...
}
// In the script:
class ExtendedMap : Map
{
void Load()
{
if (m_mapid == 1234)
printf("Map 1234 has been loaded");
Map::Load();
}
}
And then I want every instance of Map in both the core and scripts to actually be an instance of ExtendedMap.
Is that possible? How?
The inheritance is possible. I don't see a solution for replacing the instances of Map with instances of ExtendedMap.
Normally, you could do that if you had a factory class or function, that is always used to create a Map object, but this is a matter of existing (or inexistent) design.
The only solution I see is to search in the code for instantiations and try to replace them by hand. This is a risky one, because you might miss some of them, and it might be that some of the instantiations are not in the source code available to you (e.g. in that old DLL).
Later edit
This method overriding also has a side effect in case of using it in a polymorphic way.
Example:
Map* pMyMap = new ExtendedMap;
pMyMap->Load(); // This will call Map::Load, and not ExtendedMap::Load.
This sounds like a textbook case for the "Decorator" design pattern.
Although it's possible, it's quite dangerous: the system should be open for extension (i.e. hooks), but closed for change (i.e. overriding/redefining). When inheriting like that, you can't anticipate the behaviour your client code is going to show. As you see in your example, client code must remember to call the superclass' method, which it won't :)
An option would be to create a non-virtual interface: an abstract base class that has some template methods that call pure virtual functions. These must be defined by subclasses.
If you want no core Map's to be created, the script should give the core a factory to create Map descendants.
If my experience with similar systems is applicable to your situation, there are several hooks registered. So basing a solution on the pattern abstract factory will not really work. Your system is near of the pattern observer, and that's what I'd use. You create one base class with all the possible hooks as virtual members (or several one with related hooks if the hooks are numerous). Instead of registering hooks one by one, you register one object, of a type descendant of the class with the needed override. The object can have state, and replace advantageously the void* user data fields that such callbacks system have commonly.