Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you pass 'this' as an argument to another class constructor without circular dependencies?

I'm thinking specifically of the Strategy pattern (Design Patterns, GoF94), where it is suggested that the context passed to the strategy constructor can be the object which contains the strategy (as a member) itself. But the following won't work:

//analysis.h

class StrategyBase;
class Strategy1;
class Strategy2;
class Analysis
{
   ...
      void ChooseStrategy();
   private:
      StrategyBase* _s;
      ...
};

//analysis.cpp

void Analysis::ChooseStrategy()
{
   if (...) _s = new Strategy1(this);
   else if (...) _s = new Strategy2(this);
   ...
}

//strategy.h

#include analysis.h
...

and then StrategyBase and its subclasses then access the data members of Analysis.

This won't work because you can't instantiate Strategy* classes before they've been defined. But its definition depends on that of Analysis. So how are you supposed to do this? Replace ChooseStrategy with

void SetStrategy(StrategyBase* s) { _s = s; }

and do the instantiation in files which #include both analysis.h and strategy.h? What's best practice here?

like image 549
Matt Phillips Avatar asked May 09 '11 17:05

Matt Phillips


People also ask

How do I ignore circular dependency?

To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.

How do I get rid of cyclic dependency in Java?

A simple way to break the cycle is by telling Spring to initialize one of the beans lazily. So, instead of fully initializing the bean, it will create a proxy to inject it into the other bean. The injected bean will only be fully created when it's first needed.

What are circular dependencies among servers and how can they be avoided?

A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.

How do you find cyclic dependency in Java?

Analyze cyclic dependenciesFrom the main menu, select Code | Analyze Code | Cyclic Dependencies. In the Specify Cyclic Dependency Analysis Scope dialog, select the scope of files that you want to analyze. Select the Include test sources option if you want to analyze your test code together with the production code.


2 Answers

You will always have circular dependencies in the State/Strategy Pattern, except for very general States/Strategies. But you can limit the in-size (Lakos) use of the respective other class such that it compiles, at least:

  1. Forward-declare Analysis (analysis.h or strategies.h)
  2. Define StrategyBase and subclasses (don't inline methods that use Analysis) (strategies.h)
  3. Define Analysis (may already use inline methods that use strategies) (analysis.h)
  4. Implement Analysis and the strategy classes' non-inline methods (analysis.cpp)
like image 95
Marc Mutz - mmutz Avatar answered Sep 24 '22 20:09

Marc Mutz - mmutz


analysis.cpp also needs to include strategy.h to pick up the full definitions of the strategies. Since it's a source file there's no circular dependency.

like image 28
Mark B Avatar answered Sep 21 '22 20:09

Mark B