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.
Related
I am trying to figure out a pattern to avoid code duplication in a situation similar to the one bellow:
std::list<int> error_list;
void validate()
{
if( validate_0001() == false )
{ error_list.push_back(1); }
if( validate_0002() == false )
{ error_list.push_back(2); }
...
}
The method 'validate' is public in a class responsible for performing different actions, in the example validations, each one with an unique id. I want to be able to add a new action by just extending a base class, without the need to create a new method and add its call and its error handling inside the validate method.
I'm suggesting you use validating decorators (Here is a Java example)
abstract class Validation {
final List<Integer> list;
Validation(List<Integer> list) {
this.list = list;
}
public abstract int error();
}
class FirstValidation extends Validation {
public FirstValidation(List<Integer> list) {
super(list);
}
#Override
public int error() {
return 0;
}
}
You can't really extend a single function from a base class without extending the whole class.
One thing you can do is make the validation methods in a separate class and extend it by the two other classes. Another thing you can do is make the validations as an abstract class and implement it as you please in the child classes,the disadvantage of this approach is that you would have to provide the implementation in each of the child classes.
I would like to extend an existing piece of code, and I'm not sure about the cleanest design approach to do so. I'm wondering if the existing design really supports the kind of extension that I'm thinking of.
There is a factory which looks like this:
class XYZFactory
{
public:
static XYZFactory& getDefaultInstance() // so this is a singleton!
// ... some create methods
// std::unique_ptr<ABC> createABC();
private:
std::unique_ptr<XYZFactoryImpl> m_impl;
}
---
XYZFactory::XYZFactory() : m_impl(std::make_unique<XYZImpl>;
Now the problem is that I would like to extend the functionality of XYZImpl by deriving from it. I would like to avoid to expose that implementation detail however in the factory class, like adding a separate XYZFactory constructor with a ExtendedXYZImpl as an argument to inject that extension.
ADDED/EDITED for clarifaction: I should have called XYZImpl XYZFactoryImpl. It does the actual object creation. XYZFactory passes the createWhatever() calls to it. There is only one instance of XYZImpl which is held in m_Impl.
The thing that I actually want to be able to dynamically change is a member of XYZImpl m_ABC (instance of ABC) which is used for the object creation. I would like to derive from ABC.
Would killing the singleton design and subclassing from XYZFactory help?
Any ideas?
Thank you!
Mark
XYZFactory currently has a dependency on XYZFactoryImpl so clearly there is no way of injecting a dependency on ExtendedXYZImpl without exposing that functionality on XYZFactory. If that is unacceptable, the only alternative is to abandon the current design of XYZFactory.
There are not a great deal of constraints left in your question for us to use to form an answer but I suggest you start by making XYZFactory an abstract factory:
class XYZFactory {
public:
virtual ~XYZFactory(){}
virtual std::unique_ptr<ABC> createABC() const = 0;
}
With two implementations:
class XYZFactoryImpl : public XYZFactory {
public:
std::unique_ptr<ABC> createABC() const override {
return std::make_unique<ABC>();
}
};
class ExtendedXYZFactoryImpl : public XYZFactory {
public:
std::unique_ptr<ABC> createABC() const override {
return std::make_unique<DerivedABC>();
}
};
You can then provide a function to get a singleton instance and a way of reseating with a different singleton instance. e.g:
namespace details {
// Or this could be hidden in an anonymous namespace in a .cpp file
std::unique_ptr<XYZFactory>& getXYZFactoryInstanceMutable() {
static std::unique_ptr<XYZFactory> singleton = std::make_unique<XYZFactoryImpl>();
return singleton;
}
}
const XYZFactory& getXYZFactoryInstance() {
auto& singleton = details::getXYZFactoryInstanceMutable();
if (!singleton)
throw std::runtime_error("No XYZFactory registered");
return *singleton;
}
void setXYZFactoryInstance(std::unique_ptr<XYZFactory> new_factory) {
details::getXYZFactoryInstanceMutable() = std::move(new_factory);
}
Then to inject in your ExtendedXYZFactoryImpl you could do:
setXYZFactoryInstance(std::make_unique<ExtendedXYZFactoryImpl>());
auto abc = getXYZFactoryInstance().createABC();
Live demo.
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 we have a base fabric element interface:
class BaseFabricElenent {
public:
BaseFabricElenent(){}
virtual ~BaseFabricElenent(){}
virtual void action(){}
};
We have an enumeration:
enum TypeCode {
TypeCodeLive = 10,
TypeCodeDie = 100
};
And we have implementations for our TypeCodes.
We want to get a fabric that would return desired type by TypeCode as BaseFabricElenent* as normal fabric would do.
How to add types to fabric via preprocessor define?
say:
class LiveFabricElenent: pulic BaseFabricElenent {
public:
LiveFabricElenent() :
BaseFabricElenent(){}
virtual ~LiveFabricElenent(){}
virtual void action(){}
};
ADD_TO_FABRIC(LiveFabricElenent);
Update:
Found this helpfull article on registration of types into factory on global initialization phase
. Creating a Define that would generate stub classes for types registring is all that left.
I think you don't need a macro to achieve your purpose. If you must use the enum, do something like this:
class Fabric {
public:
BaseFabricElement* createElement(TypeCode typeCode) {
switch (typeCode) {
case TypeCodeLive: return new LiveFabricElement();
case TypeCodeDead: return new DeadFabricElement();
// ... other cases ...
default: return NULL;
}
}
};
If the creation process does not depend on Fabric state, then the createElement method can be static. I would also consider returning a smart pointer instead of a raw one, and renaming Fabric to Factory.
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?