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