Decoupling Pattern

Viewed 61

After looking at major pattern designs, I can't seem to make up my mind around the best to one to decouple classes in a big hierarchy system, specially were it concerns on avoiding injecting a Parent property in EVERY object along the way.

Some of the premises are:

  1. A child might me removed from one parent and added to another.
  2. Somewhere down the hierarchy, I need to access Parent of type X.
  3. As mentioned before, I would like to avoid injecting a Parent (either by property or constructor) to it's children.
  4. I have 1..1 and 1...N cardinalities.
  5. The hierarchy from root to furthest leaf is quite extent.

If it was a small project, I would be fine with this (pseudo code):

public abstract class BaseObject()
{
    public BaseObject Parent { get; set; }
}

public class RootObject() : BaseObject
{
    public int Id { get; }
    public ParentObject[] Parent { get; set; }
}

public class ParentObject() : BaseObject
{
    public int Id { get; }
    public ChildObject[] Parent { get; set; }
}

public class ChildObject() : BaseObject
{
    public int Id { get; }

    public void DoSomething()
    {
        //...navigate through Parent to get RootObject (or any other type in between that I might need)...
    }
}

Can anyone point me out to the right direction?

1 Answers

All these requirements remind me graph data structure:

  • A child might me removed from one parent and added to another.
  • Somewhere down the hierarchy, I need to access Parent of type X.
  • As mentioned before, I would like to avoid injecting a Parent (either by property or constructor) to it's children.
  • I have 1..1 and 1...N cardinalities.
  • The hierarchy from root to furthest leaf is quite extent.

The easiest storage would be List<Node> where each node contains links to its predecessors and successors:

class Example
{
    public List<Node> InitGraph()
    {
        var nodes = new Dictionary<string, Node>();

        nodes.Add("Head", new Node("Head"));
        nodes.Add("T1", new Node("T1"));
        nodes.Add("T2", new Node("T2"));
        // While that works, a method is nicer:
        nodes.Add("C1");

        // These two lines should really be factored out to a single method call
        nodes["Head"].Successors.Add(nodes["T1"]);
        nodes["T1"].Predecessors.Add(nodes["Head"]);
        nodes["Head"].Successors.Add(nodes["T2"]);
        nodes["T2"].Predecessors.Add(nodes["Head"]);

        // Yes. Much nicer
        nodes.Connect("Head", "C1");
        nodes.Connect("T1", "C1");
        nodes.Connect("T2", "C1");

        var nodelist = new List<Node>(nodes.Values);
        return nodelist;
    }
}

and NodeHelper class:

public static class NodeHelper
{        
    public static void Add(this Dictionary<string, Node> dict, string nodename)
    {
        dict.Add(nodename, new Node(nodename));
    }
    public static void Connect(this Dictionary<string, Node> dict, string from, string to)
    {
        dict[ from ].Successors.Add(dict[ to ]);
        dict[ to ].Predecessors.Add(dict[ from ]);
    }
}

and Node class:

public class Node
{
    public string Name { get; set; }
    public int Coolness { get; set; }
    public List<Node> Predecessors { get; set; }
    public List<Node> Successors { get; set; }
    public Node()
    {
        Coolness = 1;
    }

    public Node(string name) : this()
    {
        this.Name = name;
    }
}


    
Related