Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

The following article explains the usage of the composition design pattern in environments that do not allow multiple-inheritance of classes. Note: All code examples are written in C#.

In Java and .NET multiple-inheritance can be achieved through interfaces, but not through classes. In order to compensate for this, we can use the composition design pattern. In many cases, the composition pattern provides a better implementation than multiple-inheritance of classes because it is not concerned with merging the behaviours of multiple ancestor objects. The composition design pattern defines an object which holds instances to ancestor objects (as opposed to inheriting them). In order for the object to behave like its ancestors, it must also inherit interfaces for those objects.

Consider the following code, which demonstrates the composition design pattern:

//Interface to object A
public interface IA
{
    void PrintMessage();
    void DoA();
}

//Interface to object B
public interface IB
{
    void PrintMessage();
    void DoB();
}

//Concrete implementation of object A (implementing interface IA)
public class A : IA
{
    public void PrintMessage()
    {
        Console.WriteLine("Hello from A");
    }

    public void DoA()
    {
        Console.WriteLine("Do Job A");
    }
}

//Concrete implementation of object B (implementing interface IB)
public class B : IB
{
    public void PrintMessage()
    {
        Console.WriteLine("Hello from B");
    }

    public void DoB()
    {
        Console.WriteLine("Do Job B");
    }
}

//Concrete implementation of object C (implementing interfaces IA and IB)
public class C : IA, IB
{
    private A a = new A();
    private B b = new B();

    public void PrintMessage()
    {
        a.PrintMessage();
        b.PrintMessage();
    }

    public void DoA()
    {
        a.DoA();
    }

    public void DoB()
    {
        b.DoB();
    }
}

Objects A and B can be assigned from IA & A and IB & B respectively. Object C can be assigned from IA, IB and C, but not A or B (as with multiple-inheritance). Regardless of design pattern or implementation, without multiple-inheritance, C can never be assigned from A or B, unless it directly inherits one of these classes, and even then it will only inherit that one, and not the other. Additionally, with regards to maintainability, it is not instantly visible that C is using the composition design pattern.

In some instances, generics can improve the way the composition design pattern is implemented. Suppose using the example above, class C only inherits IA and IB, but never inherits a concrete class. This leaves C open to inherit from one concrete class.

Consider the following code sample which implements the composition design pattern:

public abstract class CompositeModel<T1, T2>
{
    //object instances are visible through (single) inheritance
    protected T1 instanceOfType1;
    protected T2 instanceOfType2;

    //default constructor should not be called since T1 and T2 are unknown at this point.
    private CompositeModel()
    {
    }

    //this constructor allows implementations to be passed in at runtime.
    public CompositeModel(T1 inst1, T2 inst2)
    {
        this.instanceOfType1 = inst1;
        this.instanceOfType2 = inst2;
    }
}

Given that the generic class performs the instantiation of ancestor classes, we can now define class C as follows:

public class C : CompositeModel<A, B>, IA, IB
{
    public C() : base(new A(), new B())
    {
    }

    public void PrintMessage()
    {
        this.instanceOfType1.PrintMessage();
        this.instanceOfType2.PrintMessage();
    }

    public void DoA()
    {
        this.instanceOfType1.DoA();
    }

    public void DoB()
    {
        this.instanceOfType2.DoB();
    }
}

By using the given generic class, the developer no longer needs to concern themselves with understanding or maintaining the composition of A and B in class C. With regards to maintainability, it is now much easier to recognise that C is using the composition design pattern because it inherits from CompositeModel, and we can also distinguish which object types are being used to create the composition given the generic type arguments. In addition to this, class C maintains implementation of IA and IB, and therefore should remain backwards compatible with existing code.

class C can be assigned in the following ways:

C instance = new C();
IA instance = new C();
IB instance = new C();
CompositeModel<A, B> instance = new C();

Assigning C like so: CompositeModel<A, B> instance = new C(); is actually pretty useless as CompositeModel does not implement any methods from its generic type parameters. CompositeModel is only concerned with the instantiation and coupling as part of the composition design pattern. The rest is maintained in any related interfaces and derived classes (i.e. C)

This implementation lends itself to both loosely and tightly coupled composition models since both classes and interfaces can be used as generic type parameters.

Consider the following code example which implements a tightly coupled composition model:

public class C : CompositeModel<A, B>, IA, IB
{
    Public C() : base(new A(), new B())
    {
    }

    public void PrintMessage()
    {
        this.instanceOfType1.PrintMessage();
        this.instanceOfType2.PrintMessage();
    }

    public void DoA()
    {
        this.instanceOfType1.DoA();
    }

    public void DoB()
    {
        this.instanceOfType2.DoB();
    }
}

This model is tightly coupled because the CompositeModel is always expecting A and B (or descendants of these concrete classes). Class C's constructor calls the base constructor and passes in instances of type A and B (or descendants).

Consider the following code example which implements a loosely coupled composition model:

public class C : CompositeModel<IA, IB>, IA, IB
{
    Public C(IA a, IB b) : base(a, b)
    {
    }

    public void PrintMessage()
    {
        this.instanceOfType1.PrintMessage();
        this.instanceOfType2.PrintMessage();
    }

    public void DoA()
    {
        this.instanceOfType1.DoA();
    }

    public void DoB()
    {
        this.instanceOfType2.DoB();
    }
}

This implementation allows anything assignable from IA and IB to be instantiated via the CompositeModel, therefore is not tied down to just A and B concrete implementations or descendants. C’s default constructor could be implemented to use A and B, however another constructor here provides access for the developer to pass in their own implementations of IA and IB.

share|improve this question

migrated from stackoverflow.com Aug 11 '12 at 0:20

6 Answers

up vote 3 down vote accepted

As this is CodeReview.SE, let's review:

public abstract class CompositModel<T1, T2>
{
    //object instances are visible through (single) inheritance
    protected T1 instanceOfType1;
    protected T2 instanceOfType2;

Not bad, but isn't the idea to create a class that implements the interface of T1 and T2, allowing you to composite the two and pass one instance as either dependency? You can't define a class to be the child of a GTP, unfortunately, so the whole thing is a bit moot; it's just one more way to define that children of this class can fulfill two dependencies.

    //default constructor should not be called since T1 and T2 are unknown at this point.
    private CompositModel()
    {
    }

Actually, a default constructor could be used; unlike methods, constructors cannot imply generic types based on input parameters, so you would have to explicitly specify the GTPs. However, allowing use of a default constructor would require the instances to be injectable by property instead of by constructor, meaning they'd have to be public and mutable. If that's not feasible, then you should actually remove the whole constructor declaration; C# only generates a public default constructor for a class if no other constructor exists.

    //this constructor allows implementations to be passed in at runtime.
    public CompositModel(T1 inst1, T2 inst2)
    {
        this.instanceOfType1 = inst1;
        this.instanceOfType2 = inst2;
    }
}

Yes it does, and it's probably the only way you should ever instantiate one of these, but understand that users will probably want to specify GTPs that are the interfaces of the passed constructor parameters.

If you absolutely, positively wanted to dynamically composite two implementations of different interfaces into a type that inherited the interfaces and made "pass-through" calls to the implementations, your best bet would probably be a static generic method that took two objects, allowed you to explicitly define the interface types as GTPs, and emitted the composite.

share|improve this answer
Absolutely, the idea is to create a class that implements interfaces for T1 and T2. The generic class is only half of the solution. (using my examples as a reference)- Class C performs the contractual implementation. This is not done by CompositModel as this would defeat the object of using the generic class. The generic class is only concerned with instantiation and dependency as part of the composition pattern. – series0ne Aug 15 '12 at 21:27

Please discuss, I am very interested to know your opinion on this implementation of composition modelling.

How does this help? Does this improve clarity compare to using simple delegation?

If I have a Laser Shark I can use

class LaserShark implements Armed, Animal {
    final Shark shark;
    final Lazer laser;

    // call methods using shark and laser.

If I use instance1 and instance2 I could confuse which is which, but with shark and laser its pretty clear.

share|improve this answer

Using generics doesn't seems a good idea to me. You can simply using composition to encapsulate A and B inside C.

public class C : IA, IB
{
    private IA a;
    private IB b;

    public C(IA a, IB b)
    {
        this.a = a;
        this.b = b;
    }
    void PrintMessage()
    {
        Print("Hello from C");
    }

    void DoItForA()
    {
        a.DoItA();
    }

    void DoItForB()
    {
        b.DoItB();
    }
}

Side note: from inside C it's better referring A and B through their interface IA and IB. This way you decouple C from A and B concrete implementation.

share|improve this answer
+1 for coupling to interfaces – tallseth Nov 16 '12 at 3:36

I still think composition is the best way to deal with the situation. What's wrong with:

class C
{
    A a;
    B b;

    public C()
    {
       a = new A();
       b = new B():
    }
}

For a better, more efficient way of utilizing composition, see this answer.

share|improve this answer

Why are you implementing IA and IB interfaces in class C? Look at the line from your code for reference

public class C : CompositModel<A, B>, IA, IB
share|improve this answer
Because C should contractually implement IA and IB, so as to be assignable from these interfaces – Matthew Layton Aug 10 '12 at 15:38

Why not just let C create A and B in its ctor? Wouldn't this accomplish exactly the same, because you are already coupling C to A and B?

public class C : IA, IB
{
    private IA instanceOfA;
    private IB instanceOfB;

    public C()
    {
       this.instanceOfA= new A();
       this.instanceOfB= new B();
    }

    void PrintMessage()
    {
        this.instanceOfA.PrintMessage();
        this.instanceOfB.PrintMessage();
    }

    void DoItForA()
    {
        this.instanceOfA.DoItForA();
    }

    void DoItForB()
    {
        this.instanceOfB.DoItForB();
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.