Imagine I have an abstract class Node
which has several methods and attributes. (Join a network, send a message, broadcast ...).
I want to be able to add/remove functionality to/from that Node
class (Routing functionality, mining functionality, ...)
I was thinking about using a Decorator pattern since that let's me change the behaviour of that class dynamically on runtime.
return new RoutingNode(new BaseNode(name));
But now, I' starting to think that this is not the right choice since I'm using an abstract base class over an interface.
Basically I want to know if it's possible to add functionality to an existing object without subclassing the base class. For example, I want to add Routing functionality to let a node know he's able to route incoming requests or Mining functionality to let the node perform mining tasks. But this should be interoperatable meaning I can add add or remove functionality on runtime.
What would be the most elegant and best way to handle my use case scenario.
2 Answers 2
I am not aware of your complete plan, but I suspect, that what you are trying to do violates SRP.
One class should have only one responsibility. You can add a single functionality to your Node class via inheritance, but adding two kinds of functionality now violates SRP.
You can leave your Node as an object, that represents an actor and use, well, Commands for instance, to perform actions. I can't propose something good without having knowledge of your domain, but I think you got an idea.
-
To make myself more clear, I want to know if it's possible to add functionality to an existing object without subclassing the base class. For example, I want to add Routing functionality to let a node know he's able to route incoming requests or Mining functionality to let the node perform mining tasks. But this should be interoperatable meaning I can add add or remove functionality on runtime to a given node. I'm wondering if there's a good design pattern to handle this kind of situation.Verhelst– Verhelst01/20/2018 09:29:58Commented Jan 20, 2018 at 9:29
Several times I've been facing the problem of having some kind of a graph (tree actually) and needed to do some operations with those nodes. In my case I wanted to split a 3D world into Quadtrees. But rendering was something else... I had to traverse the Quadtree nodes and do a rendering on it. Ie I split DATA and OPERATIONS which I suggest you should do.
On the other hand, there were times when I wanted to store some kind of metadata with my nodes depending on the OPERATIONS i wanted to do (performance reasons). So the solution was to be able to add some kind of custom Data to the nodes.
enum CustomDataType {SomeMiningData = 0, SomeRoutingData}
class ICustomData{
virtual CustomDataType GetType() = 0;
}
class AdditionalDataContainer{
void SetCustomData(ICustomData data);
ICustomData GetCustomData(CustomDataType type);
}
class Node{
AdditionalDataContainer additionalData;
}
Well the types and setters for custom data isn't important but you get the point.
Explore related questions
See similar questions with these tags.
invoke($commandName, $params)
method on your object. You can create a method to check if certain object has certain command likehasCommand($commandName)
, but this is something you should think twice about before you start implementing such things.