2

I have this design which I self-proclaim to be Composite Pattern, though I'm not entirely sure about that. So I'm aksing for your statement on this.

This is the interface which collectively describes all of them

public interface DomainResourceBuilder<T extends DomainResource> {

    T buildInsertion(T persistence, EntityManager entityManager) throws Exception;

    T buildUpdate(T model, T persistence, EntityManager entityManger);

    <E extends T> DomainResourceBuilder<E> and(DomainResourceBuilder<E> next);

}

This one describes DomainResourceBuilder as a pair

public abstract class AbstractDomainResourceBuilder<D extends 
    DomainResource> implements DomainResourceBuilder<D> {

    @Override
    public <E extends D> DomainResourceBuilder<E> 
        and(DomainResourceBuilder<E> next) {
        return new CompositeDomainResourceBuilder<>(this, next);
    }

    private class CompositeDomainResourceBuilder<T extends D> 
        extends AbstractDomainResourceBuilder<T> {

        private final DomainResourceBuilder<D> parentBuilder;
        private final DomainResourceBuilder<T> childBuilder;

        public 
           CompositeDomainResourceBuilder(DomainResourceBuilder<D> 
           parentBuilder,
           DomainResourceBuilder<T> childBuilder) {
            super();
            this.parentBuilder = parentBuilder;
            this.childBuilder = childBuilder;
        }

        @SuppressWarnings("unchecked")
        @Override
        public T buildInsertion(T model, EntityManager 
            entityManager) throws Exception {
            return childBuilder.buildInsertion((T) 
            parentBuilder.buildInsertion(model, entityManager), 
                entityManager);
        }

        @SuppressWarnings("unchecked")
        @Override
        public T buildUpdate(T model, T persistence, 
            EntityManager entityManger) {
            return childBuilder.buildUpdate(model, (T) 
                parentBuilder.buildUpdate(model, persistence, 
                    entityManger), entityManger);
        }
    }
}

Concrete class plays the Leaf role

public class CustomerBuilder extends AbstractDomainResourceBuilder<Customer> {

    @Override
    public
        Customer buildInsertion(Customer persistence, EntityManager entityManager) throws Exception {
        return persistence;
    }

    @Override
    public
        Customer buildUpdate(Customer model, Customer persistence, EntityManager entityManger) {
        return persistence;
    }

}

Can I call this a Composite Pattern?

This is how I use it. Assumming I have the following hierarchy.

AbstractEntity
|___User
    |___Customer

Now I want to implement different logics on each class, so with the design I'll create specific logic for those class and then ultimately compose them into one, which is still one of their kind. Something like this.

// group of objects
DomainResourceBuilder<AbstractEntity> abstractEntityBuilder = new AbstractEntityBuilder<>();
DomainResourceBuilder<User> userBuilder = new UserBuilder<>();
DomainResourceBuilder<Customer> customerBuilder = new CustomerBuilder<>();
// treat them as a whole (unify them all)
DomainResourceBuilder<Customer> compositeCustomerBuilder = 
    abstractEntityBuilder
    .and(userBuilder)
    .and(customerBuilder);
2
  • At first glance looks more like an abstract factory mixed with a prototype. Composite is a structural pattern and your code seems to be strictly related to objects creation, hence my thoughts of the prototype and the abstract factory patterns. Maybe more code would be required to understand the connection to the composite pattern. Commented Jul 5, 2022 at 10:40
  • Yes, it involves instance creation. But isn't Composite Pattern described as a collection of instances, in the form of a tree, treated as a single instance and the behaviour of that single instance is unified? Commented Jul 5, 2022 at 10:44

1 Answer 1

3

I do not think that it looks like Composite pattern as:

In my view, it looks like it uses Builder pattern with generics that can treat hierarchy of entities.

UPDATE:

In my view it is not group of objects:

// group of objects
DomainResourceBuilder<AbstractEntity> abstractEntityBuilder = new AbstractEntityBuilder<>();
DomainResourceBuilder<User> userBuilder = new UserBuilder<>();
DomainResourceBuilder<Customer> customerBuilder = new CustomerBuilder<>();

If the above objects will be put in collection, then it can be called as group of objects. In my honour opinion, it is just object variables.

In the following lines of code, Fluent interface design pattern can be seen as methods can be chained:

// treat them as a whole (unify them all)
DomainResourceBuilder<Customer> compositeCustomerBuilder = 
    abstractEntityBuilder
    .and(userBuilder)
    .and(customerBuilder);

Let me show an example where group of objects can be treat as a whole.

The following literature has great examples and explanations:

Imagine you are building browser and you want to show controls. Your task is to show values of all of your controls placed in DOM browser.

So example code would look like this.

We need some base class for controls:

public abstract class ControlBase
{
    protected string name;
    protected string value;

    public ControlBase(string name, string value)
    {
        this.name = name;
        this.value = value;
    }

    public abstract string ShowValue();
}

and its operations:

public interface IControlOperations
{
    void Add(ControlBase gift);
    void Remove(ControlBase gift);
}

Then we create a composite control where we can have group of objects:

public class CompositeControl : ControlBase, IControlOperations
{
    // group of objects
    private List<ControlBase> _controls;

    public CompositeControl(string name, string value)
        : base(name, value)
    {
        _controls = new List<ControlBase>();
    }

    public void Add(ControlBase gift)
    {
        _controls.Add(gift);
    }

    public void Remove(ControlBase gift)
    {
        _controls.Remove(gift);
    }

    // group of objects can be treat as a whole
    public override string ShowValue()
    {
        StringBuilder allValues = new StringBuilder();

        Console.WriteLine($"{name} has the following values:");

        foreach (var gift in _controls)
        {
            allValues.AppendLine(gift.ShowValue());
        }

        return allValues.ToString();
    }
}

And our UI controls:

public class TextBox : ControlBase
{
    public TextBox(string name, string value)
        : base(name, value)
    {
    }

    public override string ShowValue()
    {
        Console.WriteLine($"{name} has {value}");

        return value;
    }
}

public class CheckBox : ControlBase
{
    public CheckBox(string name, string value)
        : base(name, value)
    {
    }

    public override string ShowValue()
    {
        Console.WriteLine($"{name} with value {value}");

        return value;
    }
}   

And then we can call code like this:

var textBox_Phone = new TextBox("textBox_Phone", "1");
textBox_Phone.ShowValue();
Console.WriteLine();
//composite control
var divContainer = new CompositeControl("divContainer", string.Empty);
var textBox_Name = new TextBox("textBox_Name", "Joseph");
var textBox_Surname = new TextBox("textBox_Surname", "Albahari");
divContainer.Add(textBox_Name);
divContainer.Add(textBox_Surname);
Console.WriteLine($"Total values of this composite control " +
    $"is: {divContainer.ShowValue()}");
Sign up to request clarification or add additional context in comments.

4 Comments

There's still something in my head yells "Composite". Maybe I'll provide more context and use cases to it. Can you check my edit
@NgọcHy please, see my updated answer
thank you, I finally got the concept thanks to your example
@NgọcHy I am glad that it helped to you! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.