Take the 2-minute tour ×
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.

UPDATE (for .NET users):

Consider using the Tuple<T,[T]> class instead of implementing CompositeModel.

share

migration rejected from stackoverflow.com Apr 4 at 9:36

This question came from our site for professional and enthusiast programmers. Votes, comments, and answers are locked due to the question being closed here, but it may be eligible for editing and reopening on the site where it originated.

closed as unclear what you're asking by 200_success Apr 4 at 9:36

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question.If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer 1

up vote 4 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
    
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

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