javadesign-patternscomposite

Can I call this an implementation of the Composite Pattern


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);

Solution

  • 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()}");