I want to define plugin like objects for my program. They should look like this:
class ModuleBase
{
public :
void baseFunction1();
void baseFunction2();
...
virtual void init() = 0;
virtual void finalize() = 0;
};
class SpecificModule : public ModuleBase
{
public :
virtual void doSpecificTask() = 0;
};
Thus I will have SpecificModule implementations:
class ConcreteSpecificModule1 : public SpecificModule
{
public :
void init();
void finalize();
void doSpecificTask();
};
In order to mask implementation and complexity, I want my modules to see the underlying system through a facade Interface :
class SystemViewForSpecificModule
{
public :
virtual SystemData& getData(//some parameters) = 0;
virtual void doSystemAction1() = 0;
virtual void doSystemAction2() = 0;
...
};
Finally I want to be able to make several programs that can deal with Module and / or SpecificModule instances.
Considering I have prog1, prog2, and prog3, I will have to implement
Prog1View, Prog2View and Prog3View as concrete implementations of SystemViewForSpecificModule interface.
Additionally, I have to consider the following case :
Prog2 will embed Prog1 and I want to be able to do this :
instantiate the SpecificModule instances
run the prog1 part that make calls to SpecificModule::doSpecificTask();
run the prog2 part that also call SpecificModule::doSpecificTask();
My question is: How to pass / store the reference (or pointer) to the system in the SpecificModule instances ?
1 - Storing the reference at construction time :
thus the SpecificModule interface should like
class SpecificModule : public ModuleBase
{
SystemViewForSpecificModule& m_sys;
public :
SpecificModule(SystemViewForSpecificModule& sys):m_sys(sys){}
virtual void doSpecificTask() = 0;
};
This is a pleasant way to achieve my problem, but don't forget that in prog2 I have first to
run my modules with prog1, thus I have to switch from SystemViewForSpecificModule implementation dynamically in this case.
(+) Modules can access to system during their whole life and all method can get access to it.
(-) Once the reference set, it can not be changed
We can consider that using a reference is not a good solution, or use something like this:
class SystemView : public SystemViewForSpecificModule
{
SystemViewForSpecificModule* concreteSystem;
public
SystemView(SystemViewForSpecificModule& sys)
{concreteSystem = &sys;}
void setSystem(SystemViewForSpecificModule& sys)
{concreteSystem = &sys;}
void doSystemAction1()
{concreteSystem->doSystemAction1();}
...
}
This way, the module doesn't even know that the implementation has changed
However, I'm afraid it will reduce performance due to extra vtable access.
2 - Using a setter to specify the system view
The SpecificModule interface should like:
class SpecificModule : public ModuleBase
{
SystemViewForSpecificModule* m_sys;
public :
setSystem(SystemViewForSpecificModule& sys){m_sys = &sys;}
virtual void doSpecificTask() = 0;
};
That seems to be a convenient solution but I don't like the fact that the module has:
the knowing of this change
to handle this change
to check the validity of the pointer before using it
3 - Passing references to SpecificModule methods
At least the SpecificModule interface will look like that:
class SpecificModule : public ModuleBase
{
virtual void doSpecificTask(SystemViewForSpecificModule& sys) = 0;
};
I don't like to pass the same reference 10000 times to the same function (both prog1 and prog2 part will call it lot of times).
Another bad point for this solution is: I don't have access to the system view in the ModuleBase methods (such as init() and finalize()). And obviously, moving them to the subclasses would reduce the inheritance interest.
What solution would you use in this example case (I hope to see other solutions than the 3 presented)?
Related
My goal here was, instead of placing all methods in ServerInterface(superclass), i wanted to place the methods in child classes to organize the code better.
class ServerInterface
{
public:
Router* router = new Router();
Client* client = new Client();
ServerInterface() {
} //Creates new Router and Client instance
};
class Router : public ServerInterface
{
public:
Router() {}
void randomRouterFunction() {}
};
class Client : public ServerInterface
{
public:
Client() {}
virtual void randomClientFunction() {};
};
class ProductionServer : public ServerInterface
{
public:
ProductionServer() {}
};
int main() {
ProductionServer* productionServer = new ProductionServer();
productionServer->router->randomRouterFunction(); //causes it to not debug
return 0;
}
In my situation I am only allowed to access to ProductionServer which has to inherit from ServerInterface in my code.
So instead of calling productionServer->randomRouterFunction() or productionServer->randomClientFunction(), i wanted to be able to call productionServer->Router->randomRouterFunction() etc
Even though intellisense tells me that it's all working fine, trying to run my code i recieve
main:289:20: error: 'class ProductionServer' has no member named
'router'
productionServer->router->randomRouterFunction();
Is this even feasible to accomplish? The reason for thinking it may not work is cause the superclass creates a member of Router which is the child class, and then the router child class creates another superclass since it inherits it, which then creats another router child class in the superclass.... and it would be an infinite loop? XD
ps. The randomFunction() could be any method, just used as an example.
The problem is with the design. You can compile this but when you create a ProductionServer it will instantiate a ServerInterface which will create a Router and a Client and those will both also instantiate a ServerInterface that will create a Router and a Client and so on - until you get a stack overflow.
In order to get this in some working condition, you need to add something that breaks that cycle so that it doesn't instantiate Routers and Clients endlessly.
For an Object Adapter design, GoF states :
makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself
My question is that why is this subclassing required when we are creating the clases as follows :
class Target {
public :
virtual void op() = 0 ;
} ;
class Adaptee {
public :
void adapteeOp() {cout<<"adaptee op\n" ;}
} ;
class Adapter : public Target {
Adaptee *adaptee ;
public :
Adapter(Adaptee *a) : adaptee(a) {}
void op() {
// added behavior
cout<<"added behavior\n" ;
adaptee->adapteeOp() ;
// more added behavior
cout<<"more added behavior\n" ;
}
} ;
main() { //client
Adapter adapter(new Adaptee) ;
adapter.op() ;
}
I have not been able to appreciate the requirement for subclassing as mentioned by GoF when I am able to override the behavior here also.
Please explain what is the point that I am missing out.
I have not been able to appreciate the requirement for subclassing as mentioned by GoF when I am able to override the behavior here also.
I see your confusion. Your example is too simple as it only contains cout statements. I wouldn't qualify adding cout statements before and after a call to one of Adaptees methods as adding any significant behavior. You need to consider more complex scenarios.
Imagine that you want to add newFunctionality to the Adaptee that uses the protected data from Adaptee. You can't modify the Adaptee so the only option you have is to subclass it.
class NewAdaptee : public Adaptee {
public :
void adapteeOp() {
cout<<"adaptee op\n" ; //step 3
}
void newFunctionality() { //use protected members from Adaptee }
} ;
The above code demonstrates a more complex use case of adding functionality to the Adaptee where subclassing is the only way to achieve this. So you now want to start using this new Adaptee in your Adapter. If you go with the object adapter option, you will need to start using a NewAdaptee reference in the Adaptor
class Adapter : public Target {
NewAdaptee *adaptee ;
//more code follows
}
This has the immediate issue that your Adapter can no longer be passed any direct subclasses of Adaptee. This is what they mean when they say It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself. This would take away the advantage of the object adapter approach which was to allow a single adapter to work with all the subclasses of the Adaptee.
Note : In the class adapter approach, NewAdaptee would actually be your adapter and would also inherit Target.
Let’s say I’m writing a car class. It should have the methods configEngine and currentGasolineConsumption beside some other methods. So I refactored out the calculation of the gasoline consumption into an Engine class and use polymorphism to get the current gasoline consumption:
class AbstractEngine()
{
public:
virtual int calculateGasolineConsumption()
{
//... do calculation ...
return consumption;
}
// some other (pure virtual) methodes
};
class EngineA() : public AbstractEngine
{
public:
// implementation of the pure virtual methodes
};
class EngineB() : public AbstractEngine
{
public:
// implementation of the pure virtual methodes
};
class EngineC() : public AbstractEngine
{
public:
// implementation of the pure virtual methodes
int calculateGasolineConsumption() override
{
//... do new calculation ...
return consumption;
}
};
enum EngineType {
ENGINE_A,
ENGINE_B,
ENGINE_C,
};
void configEngine(EngineType engineType)
{
m_engine = m_engineFactory.create(engineType);
}
int currentGasolineConsumption()
{
return m_engine.calculateGasolineConsumption();
}
Now my question is how to unittest this without getting duplication in my unit tests?
If I write three unittests, for configEngine(ENGINE_A) and configEngine(ENGINE_B) would test basically the same code of the abstract superclass and I don’t like that duplication.
struct EngineSpec {
EngineType engineType;
int expectedValue;
};
INSTANTIATE_TEST_CASE_P(, tst_car, ::testing::Values(
EngineSpec { ENGINE_A, 3 },
EngineSpec { ENGINE_B, 3 },
EngineSpec { ENGINE_C, 7 }
));
TEST_F(tst_car,
currentGasolineConsumption_configWithEngine_expectedBehaviour)
{
EngineSpec engineSpec = GetParam();
//Arrange
m_car.configEngine(engineSpec.engineType);
//Act
auto result = m_car.currentGasolineConsumption();
//Assert
EXPECT_EQ(engineSpec.expectedValue, result);
}
Of course there is only one duplicate/unnecessary unittest but this is only a minimal example. In my real code the number of unit test duplication would explode.
One additional thing: I don’t want to move the Engine class outside of the ‘module’ and use dependency injection because I think this ‘internal Engine class’ approach is easier to handle for the client. So the client has only one interface and some enums to use this module. I would like to treat the Engine class as implementation detail.
Ideally tests should know as little about the implementation as possible, because 10 years down the line when the abstraction doesn't quite work any more, or is part of a large complicated inheritance chain (e.g. what happens when you get a hybrid engine?) the tests that appear to be a lot of effort right now will still work perfectly.
However, if you want to be pragmatic and don't mind coupling your tests to the implementation a little, you could extract a testGasolineConsumption(AbstractEngine engine) method that is called from a test case for each child. This would check that the implementation works correctly and that the base class behaviour hasn't been overridden.
Say i have an hierarchy of Shape objects, each has its own data (polyline has list of vertices, circle has a center and radius, etc).
I want to be able to perform operations on each shape, such as Draw, Snap to some point, split to two shapes at a specific point, etc.
One way to do it is to add a method to Shape interface for each operation. However, in that case i will have to modify my model interface every time a new operation is added. It does not sound correct to me. I thought of the following solution and would like to here your opinion or other solutions.
I will add an interface of ShapeOperationsFactory and the following method to Shape interface:
class Shape
{
public:
virtual ShapeOperationFactory* createShapeOperationsFactory() = 0;
};
class Circle : public Shape
{
public:
virtual ShapeOperationsFactory* createShapeOperationsFactor();
};
ShapeOperationsFactory* Circle::createShapeOperationsFactory()
{
return new CircleShapeOperationsFactory();
}
ShapeOperationsFactory will be able to create a set of operations classes that are specific for the shape:
class ShapeOperationsFactory
{
public:
virtual ShapeDrawer* createDrawer() = 0;
virtual ShapeSnapper* createSnapper() = 0;
virtual ShapeSplitter* createSplitter() = 0;
};
class CircleShapeOperationsFactory : public ShapeOperationsFactory
{
public:
virtual ShapeDrawer* createDrawer();
virtual ShapeSnapper* createSnapper();
virtual ShapeSplitter* createSplitter();
}
ShapeDrawer* CircleShapeOperationsFactory::createDrawer()
{
return new CircleShapeDrawer();
}
ShapeSnapper* CircleShapeOperationsFactory::createSnapper()
{
return new CircleShapeSnapper();
}
ShapeSplitter* CircleShapeOperationsFactory::createSplitter()
{
return new CircleShapeSplitter();
}
In this implementation the Shape interface will not change when new operations are added. For new shape i will need to implement a new operations factory and a class per operation. For new operations i will need to add a method to the operations factory class and a class implementing the operation for each shape.
Making your classes more modular by creating an Operator class I think is great, but this is not really a factory. Factory usually involved creating an object base on some message, for example on a unserialization process.
For your case you could have an Operator member in your base class and in the constructor of your derived class you assign that member to the appropriate Operator derived class.
A solution could be to use the visitor design pattern. The purpose of this design pattern :
the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures. It is one way to follow the open/closed principle.
The principle is simple:
You create a visitor class:
class Visitor
{
public:
virtual void visit(Circle*) = 0;
virtual void visit(Polyline*) = 0;
...
};
You add this method to Shape:
virtual void accept(class Visitor*) = 0;
Then you implements this method in each Shape sub class.
void Circle::accept(Visitor *v)
{
v->visit(this);
}
And then you have to create one visitor per operation:
class Drawer: public Visitor
{
public:
Drawer()
{
}
void visit(Circle* c)
{
drawCircle(c);
}
void visit(Polyline*p)
{
drawPolyline(p);
}
...
};
You could also delegate each visit method to a service: (visit(Circle* c) to a CircleDrawer).
void visit(Circle* c)
{
circleDrawer->draw(c);
}
void visit(Polyline*p)
{
polylineDrawer->draw(p);
}
If you want to add an operation, you will have to create a new visitor sub class.
If you want to add a shape, you will have to add a new method on each visitor.
The visitor collaborare really well with the composite design pattern (heavily use in gui programming). The visitor pattern can be used in addition with the composite pattern. The object structure can be a composite structure. In this case in the implementation of the accept method of the composite object the accept methods of the component object has to be invoked.
Note:
I am not a c++ programmer, feel free to edit and make the code syntactically correct.
I am in a situation where I'm going to do a multiple inheritance (and the diamond of dread kind of). I'd like to avoid that, so hopefully someone has an idea to do it another way.
I want to make a library that handle network connections. I have an abstract factory with method to create a tcpServer, tcpClient, udp, and a last method that create an entry from a directory (config file is given to the init method of the factory). So I've created classes (actually interfaces) to this kind of connections. Entry is the base interface. To simplify, let's just say that it has methods to set data and status callback. All other classes (tcpClient ...) inherits from this one.
I want to do an implementation of this factory using boost, so I have to implement all the classes (tcpServer, …). The problem is that all class implementations require a common base. Here is what I'm going to do, but I'm not sure that's the right way to do it:
Here is the abstract part:
// The abstract factory:
class Factory
{
virtual IO::TcpServer* createTcpServer() = 0;
virtual IO::TcpClient* createTcpClient() = 0;
virtual IO::Entry* createFromConf() = 0;
};
// The Entry interface:
class Entry {
virtual bool isChild() const = 0;
// ...
virtual void setDataCbk() = 0;
virtual void setStateCbk() = 0;
};
// TcpClient interface
class TcpClient : public IO::Entry {
/* Nothing yet but stuff will come */
};
Here is the boost implementation (Class names are same but in different namespaces; I don't show the factory implementation):
// Entry first step of implementation (still abstract)
class Entry : public IO::Entry
{
virtual void setDataCbk();
virtual void setStateCbk();
};
// Flat entry : entry that can't have child (like tcp client, udp ...)
class FlatEntry : public IO::Boost::Entry
{
virtual bool isChild() const; // Will always return false
// ...
};
// The final TcpClient implementation
class TcpClient : public IO::TcpClient
, public IO::Boost::FlatEntry
{
// ...
};
So I'm worried about this multiple inheritance thing. On the other hand, super classe is a pure interface (no data, only pure virtual methods). Any ideas?