Question about abstract factories and injections

This seems like one of my other questions, but in a different way I think to ask a new question.

I mainly write the user interface, and my user interface has nodes that can be selected. When node is selected, the user interface ends with the abstract base class node "INode". From this, I get the factory by executing node โ†’ getFactory (), and from this I can create the appropriate dialogs or views for this node, because the correct factory is returned by the concrete node (e.g. factory โ†’ createAddDialog (), factory โ†’ createView (node) and so on .d.).

My question is trying to find the best way for this factory to break into node first.

So far I have been thinking of three ways:

1) Add the correct factory when I create the node:

AreaNode *node = new AreaNode(new AreaNodeFactory()); 

Thus, the definition of AreaNode:

 AreaNode : public INode { AreaNode(INodeAbstractFactory *injectedFactory) { m_injectedFactory = injectedFactory; } INodeAbstractFactory* getFactory() { return m_injectedFactory; } INodeAbstractFactory* m_injectedFactory; }; 

2) Introduce a more general factory and let node get a factory from this factory:

 AreaNode : public INode { AreaNode(IFactory *injectedFactory) { m_injectedFactory = injectedFactory; } INodeAbstractFactory* getFactory() { return m_injectedFactory->getAreaNodeFactory(); } IFactory* m_injectedFactory; } 

3) Just create a specific factory (although this removes the scope for using different factories for the same node, perhaps for testing or for subsequent changes):

 AreaNode : public INode { INodeAbstractFactory* getFactory() { return new AreaNodeFactory(); } } 

Current thoughts on these parameters:

Option 1: maybe a little random - I would need to make sure that I always give it the correct factory for this type, or maybe I can just use another factory to enter the correct factory for me.

Option 2: Makes node aware of the abstract factory implementation enough to be able to call getAreaNodeFactory, which might not be so bad. This at least helps to ensure that the correct / same factory will always be checked out (provided that the more general factory is implemented correctly).

Option 3: This limits me a bit since I cannot change the class, and I'm not interested in node to know about a specific factory implementation - although this is the case, this may not be a big problem (famous words!).

Any thoughts on this?

Thanks.

EDIT: Sorry, missed variable declarations in the origin column, fixed.

EDIT: Another issue with option 2 - I need to implement "getFactory" in each node type. At least with option 1, the base class can simply return a nested abstract factory class each time.

+6
c ++ oop design-patterns
source share
3 answers

What about

 class FactoryBase { /* interface */ } template <typename NodeType> class Factory : public FactoryBase { // Default implementation. } // Add appropriate specializations for all relevant nodetypes, if needed. template <typename NodeType> inline Factory<NodeType> getFactory(NodeType*) { return Factory<NodeType>( ); } class AreaNode : public Node { FactoryBase getFactory() { return getFactory(this); } }; 

The output of the template argument ensures that the type factory is derived from this . This should prevent manual errors. But overall, I would not publicly publish the factory at all. Just add the following digits to the base class:

 class Node { public: std::Auto_ptr<View> createView( ) { this->getFactory()->createView(this); } // etc. private: virtual FactoryBase* getFactory() = 0; }; 
+2
source share

What about.

 template<typename Factory> class AreaNode : public INode { public: virtual ~AreaNode(){} AreaNode() : pFactory_(new Factory()) { } const shared_ptr<IFactory>& GetFactory() { return pFactory_; } private: shared_ptr<IFactory> pFactory_; }; 

EDIT:

Or depending on your context.

 template<typename Factory> class Node { public: virtual ~Node(){} Node() : pFactory_(new Factory()) { } const shared_ptr<IFactory>& GetFactory() { return pFactory_; } private: shared_ptr<IFactory> pFactory_; }; class AreaNode : public Node<AreaNodeFactory> { // Implementation }; // OR typedef Node<AreaNodeFactory> AreaNode; 
+2
source share

Depends on the purpose of the node objects

If a factory should be entered into a node, and a specific node should not do anything with a specific type of factory, then all the associated factory code can be moved to the base node class, simplifying everything.

 class INode //well, it not "interface" in clear sense { public: void setFactory(Factory* f) { this->f = f; } Factory* getFactory() const { return f; } private: Factory* f; }; 

Now the functionality of specific units and concrete plants is produced orthogonally to each other and can be freely combined in any way.

If a particular type of node is tied to a specific type of factory, then maybe you should generally avoid factories and create views directly using the node :: createView method. Depending on whether factories are used in some other context.

Also consider this (not very OOP-ish):

 typedef boost::function0<Factory*> Node; std::map<UIItem*,Node> nodes; nodes[area_item1] = &getAreaFactory; nodes[area_item2] = &getAreaFactory; nodes[region_item1] = &getRegionFactory; ... void OnSelect(UIItem* i) { ... View* v = nodes[i]()->createView(); ... } 

Perhaps this fits all your needs)

+1
source share

All Articles