Search code examples
c#c++design-patternslanguage-agnostichierarchical-data

Best pattern for functions that apply to a preexisting class hierarchy


I have an existing class hierarchy, that I can not modify

ie a phylogenetic tree:

base
├── animal
│   ├── invertebrate
│   └── vertebrate
│       ├── amphibian
│       ├── bird
│       ├── fish
│       ├── mammal
│       └── reptile
└── plant

I need to build a library of functions for objects in that hierarchy, ie print functions:

print_mammal_A()
print_mammal_B()
print_fish_A()
print_vertebrate_A()
print_vertebrate_B()
print_animal_A()
  • These functions will be developed as they're needed.

  • There may be more than one function for each class.

The obvious solution is to make a class hierarchy of wrappers that maps the target hierarchy. Each wrapper implementing it's own function, ie:

class base_wrapper(){
  base * base_ptr;
}

class animal_wrapper : base_wrapper{
  void print_animal_A();
}

class vertebrate_wrapper : animal_wrapper {
  void print_vertebrate_A();
  void print_vertebrate_B();
}

I'd like to know of design patterns that allow either of the following items:

  • Removing wrapper inheritance (so the library developer doesn't need to know of the target class bases)

  • Automatically wrap with the most specialised wrapper for the target class (so the library user doesn't need to know of the target class bases)

I'm interested in either, C# or C++ solutions. Not sure if there are patterns that can be implemented easily in one and not the other.


Solution

  • I am assuming you cannot modify the library it self so you cannot add methods to each class?

    If I am understanding this correctly I think you could use extension methods. In C# it would be something like this.

    public static class FishExtension
    {
        public static void Print(this Fish fish)
        {
         // Now you can work with the fish object.
        }
    }   
    

    The user of fish will then be able to do:

    Fish fish = new Fish();
    fish.Print();
    

    This way there is no additional hierarchy (no wrappers) The extension class in never used directly, the user only has to import its namespace.

    See the Extension Methods (C# Programming Guide) https://msdn.microsoft.com/en-us//library/bb383977.aspx