I can't seem to figure out the best approach to tackle the following problem. Let's say there is an abstract base class with several concrete subclasses:
public abstract class AbstractType { /* common properties */ }
public class TypeA { /* properties of type A */ }
public class TypeB { /* properties of type A */ }`
These are domain classes (JPA entities). The properties of the types are (amongst other things) used to validate user data. I'm under the assumption that adding logic to the domain model itself is considered bad practice. Therefore, I want to avoid adding a validate method to the concrete subclasses. Like so:
UserInput userInput = ...;
AbstractType data = ...;
data.validate(userInput);
I don't see an option without having to cast the domain model,
if I want to move the logic to a logic layer. With the limited knowledge I have, I can only come up with following two similar "solutions", using some kind of handler interface.
Keep some explicit reference to the handler in the type
public interface TypeHandler {
public validate(AbstractType data, UserInput userInput);
}
/* TypeAHandler & TypeBHandler implementations */
public enum Type {
TYPE_A(new TypeAHandler()),
TYPE_B(new TypeBHandler());
private TypeHandler handler;
public Handler(TypeHandler handler){
this.handler = handler;
}
public TypeHandler getHandler(){ return handler; }
}
public class TypeA {
private Type type = TYPE_A;
/* ... */
}
The handler would than be called in the following manner:
UserInput userInput = ...;
AbstractType data = ...;
data.getType.getHandler().validate(data, userInput);
The reference to the handler could also be added immediately (without the enum in between) as property to the AbstractType class, but that would mean there is a reference to a class inside the logic layer from the domain model (which kind of defeats the purpose of moving the logic to a logic layer?)
The problem here too is that the validate method inside the TypeXHandler needs to cast the data argument to its subclass first before it can start validating.
Or I could implement some method which has a large if-then structure to get the right subclass, cast it and call the appropriate handler which implements an interface similar to the following.
public interface TypeHandler<T extends AbstractType> {
public validate(T data, UserInput userInput);
}
So in both cases there is casting. In the first case there is no huge if-then structure, but the logic and domain are not separated. In the second case there is a very inflexible if-then structure.
To conclude, here is my question. Should I really avoid implementing the logic directly inside the domain? If so, is there any way to avoid the casting, the if-else structure and/or adding additional properties to the domain model (like the enum in the first "solution").
At the end of the day, you're branching based on the subtype (concrete classes) since the logic to validate user input is based on those specific details contained in the subclasses.
Generics don't really help you much here since generics are based primarily on applying logic that is uniform across different types, operating on universal logic applied to a common interface that all applicable types share. Here your logic and interface varies for each subtype.
So your main choices are an inextensible solution where you're modifying central source code (like a big bunch of ifs/elses, a map, etc) and manually branching based on subtype, or using abstraction/dynamic polymorphism as an extensible solution which doesn't require modifying any central source code and automatically branches based on subtype.
Reflection might also be a possible route if you can afford it (it's a bit expensive at runtime) and provided it can fit to give you that universal logic you can implement centrally.
If you don't want to add this validate method to AbstractType and all of its subtypes, then you can always add another level of abstraction on top which does contain a validate method like ValidatorB which implements the IValidator interface and stores an object of TypeB as a member and applies the logic used to validate user input using TypeB's properties.
I studied design patterns last week and I would like to propose my solution (it works but I'm not sure that is the smartest way to resolve your problem).
The idea of my solution is to use a factory: you give a model (in your case a JPA entity) to the factory and it gives you the correct validator for that model.
At the beginning of the program, you have to tell to the factory which is the validator class for each model class of your program through a register method.
Let's start with the implementation...
AbstractModel.java
public abstract class AbstractModel
{
private final int commonProperty;
protected AbstractModel(int commonProperty)
{
this.commonProperty = commonProperty;
}
public int getCommonProperty() { return commonProperty; };
}
In the AbstractModel we put all the common properties of the models.
ModelA.java
public class ModelA extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelA(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelA has got two specific properties.
ModelB.java
public class ModelB extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelB(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelB has got two specific properties too.
Let's say that an instance a of ModelA is valid iff
a.commonProperties == a.specificProperty1 + a.specificProperty2
and an instance b of ModelB is valid iff
b.commonProperties == b.specificProperty1 * b.specificProperty2
Validator.java
public interface Validator
{
public boolean validate();
}
A really simple interface for the validators.
AbstractValidator.java
public abstract class AbstractValidator implements Validator
{
private final AbstractModel toBeValidated;
protected AbstractValidator(AbstractModel toBeValidated)
{
this.toBeValidated = toBeValidated;
}
protected AbstractModel getModel()
{
return toBeValidated;
}
}
This is the superclass of the concrete validators that wraps the model to be validated.
ValidatorA.java
public class ValidatorA extends AbstractValidator
{
protected ValidatorA(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelA modelA = (ModelA) getModel();
return modelA.getCommonProperty() == modelA.getSpecificProperty1() + modelA.getSpecificProperty2();
}
}
The validator for the instances of ModelA.
ValidatorB
public class ValidatorB extends AbstractValidator
{
protected ValidatorB(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelB modelB = (ModelB) getModel();
return modelB.getCommonProperty() == modelB.getSpecificProperty1() * modelB.getSpecificProperty2();
}
}
And this is the validator for the instances of ModelB.
And finally it comes the factory!
ValidatorFactory.java
public class ValidatorsFactory
{
private static ValidatorsFactory instance;
private final HashMap<Class<? extends AbstractModel>, Class<? extends Validator>> registeredValidators;
private ValidatorsFactory()
{
registeredValidators =
new HashMap<Class<? extends AbstractModel>, Class<? extends Validator>>();
}
public static ValidatorsFactory getInstance()
{
if (instance == null)
instance = new ValidatorsFactory();
return instance;
}
public void registerValidator(
Class<? extends AbstractModel> model,
Class<? extends Validator> modelValidator)
{
registeredValidators.put(model, modelValidator);
}
public Validator createValidator(AbstractModel model)
{
Class<? extends Validator> validatorClass = registeredValidators.get(model.getClass());
Constructor<? extends Validator> validatorConstructor = null;
Validator validator = null;
try
{
validatorConstructor = validatorClass.getDeclaredConstructor(new Class<?>[] { AbstractModel.class });
validator = (Validator) validatorConstructor.newInstance(new Object[] { model });
}
catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
System.err.println(e.getMessage());
// handle exception
}
return validator;
}
}
The factory is a singleton with two significant method:
registerValidator to add a new pair (modelClass, validatorClass) in the HashMap.
createValidator to obtain the correct validator for the specified model.
This is how to use this pattern:
public class Main
{
public static void main(String args[])
{
ValidatorsFactory factory = ValidatorsFactory.getInstance();
factory.registerValidator(ModelA.class, ValidatorA.class);
factory.registerValidator(ModelB.class, ValidatorB.class);
ModelA modelA = new ModelA(10, 4, 6);
if (factory.createValidator(modelA).validate())
System.out.println("modelA is valid");
else
System.out.println("modelA is not valid");
ModelB modelB = new ModelB(10, 8, 2);
if (factory.createValidator(modelB).validate())
System.out.println("modelB is valid");
else
System.out.println("modelB is not valid");
}
}
output:
modelA is valid [because 10 = 4 + 6]
modelB is not valid [because 10 != 8 * 2]
Note that the model is completely separeted from the controller and it uses only one cast from AbstractModel to a concrete model.
Hope it helps!
Related
I have the following Enum constants for real life equipment:
HELMET,
CHESTPIECE,
BOOTS,
SWORD,
MACE,
HAMMER,
SHIELD,
BOW,
CROSSBOW,
STAFF
...;
I have another class called Battle which dictates what equipment can be used in that specific battle. For example:
new Battle(Equipment.HAMMER, Equipment.SHIELD, EQUIPMENT.BOW);
Which means that only Hammers, Shields, or Bows can be used.
Now I expanded on that and have the need for sub categories. For example:
new Battle(Equipment.SHIELD, Equipment.Weapons.values())
Which is equivalent to saying:
new Battle(Equipment.SHIELD, Equipment.SWORD, Equipment.MACE, Equipment.HAMMER, ...) etc
Which also means that new Battle(Equipment.values()) should yield every enum value
Since Enums are final, I tried the following:
public interface Equipment { }
public enum MeleeWeapon implements Equipment
{
SWORD,
MACE,
HAMMER,
STAFF, ...;
}
public enum RangedWeapon implements Equipment
{
BOW, CROSSBOW;
}
...
But with this, I'm unable to say Equipment.Weapon.values() // get all weapons, ranged and melee. There's no sense of inherited relationships between classes, and I also lose everything that is not defined in the interface. It doesn't feel like a good solution here.
I tried making regular classes:
public abstract class Equipment
{
private static Set<Equipment> instances = new HashSet<>();
public static Set<Equipment> values()
{
return instances;
}
public Equipment()
{
instances.add(this);
}
}
public abstract class Weapon extends Equipment
{
private static Set<Weapon> instances = new HashSet<>();
public static Set<Weapon> values()
{
return instances;
}
public Weapon()
{
super() // explicit call
instances.add(this);
}
}
public class MeleeWeapon extends Weapon
{
private static Set<MeleeWeapon> instances = new HashSet<>();
public static final MeleeWeapon SWORD = new MeleeWeapon();
public static final MeleeWeapon MACE = new MeleeWeapon();
...
public static Set<MeleeWeapon> values()
{
return instances;
}
public MeleeWeapon()
{
super() // explicit call
instances.add(this);
}
}
Unfortunately there is a ton of repeated code, heavy on memory, and also public static Set<Weapon> values() causes a compile error because it attempts to override values() in the superclass with a different return type. I was able to solve this with generics (<? extends Weapon>) but it's still an awful solution.
What is the right approach here? I need inheritance with my enum values but I cannot find a way how to do so.
Still keeping the enum usage, it is possible to associate each element of the enumeration with the groups to which it belongs and then return filtered groups of elements in dedicated methods.
We'll need another - smaller - enum which enumerates the properties to filter on, for example:
public enum EquipmentType {
WEAPON, ARMOR, TOOL, CLOTHING;
}
The elements of the enumeration are associated with their respective groups:
public enum Equipment {
HELMET(ARMOR),
CHESTPIECE(ARMOR),
BOOTS(ARMOR, CLOTHING),
SWORD(WEAPON),
MACE(WEAPON),
HAMMER(WEAPON, TOOL),
SHIELD(ARMOR),
BOW(WEAPON),
CROSSBOW(WEAPON),
STAFF(WEAPON);
private final Set<EquipmentType> types;
Equipment(EquipmentType... eqTypes) {
this.types = Arrays.stream(eqTypes)
.collect(Collectors.toSet());
}
// common filtering method
private static List<Equipment> filterByType(EquipmentType type) {
return Arrays.stream(values())
.filter(eq -> eq.types.contains(type))
.collect(Collectors.toList());
}
// dedicated methods for each group of items
public static List<Equipment> getWeapons() {
return filterByType(WEAPON);
}
public static List<Equipment> getArmor() {
return filterByType(ARMOR);
}
}
There is still no inheritance or more evolved typing involved in this approach and I think it would be better to avoid using the enum at all if you want more flexibility.
One of the reasons to consider the Visitor_pattern:
A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures.
Assume that you don't have the source code of third party libraries and you have added one operation on related objects.
Since you don't have object, your elements (Third party classes) can't be modified to add Visitor.
In this case, double dispatch is not possible.
So which option is generally preferred?
Option 1: Extend one more inheritance hierarchy on top of third party class and implement pattern as show in picture with double dispatch?
For a given hierarchy of Class B which extends Class A, I will add
ElementA extends A
ElementB extends B
Now ConcreteElements are derived from ElementA instead of class A.
Cons: The number of classes will grow.
Option 2: Use Visitor class a central helper class and get the work done with single dispatch.
Cons: We are not really following Visitor patter as per UML diagram.
Correct if I am wrong.
You could combine a Wrapper and Visitor to solve your problems.
Using the wrapper to add a visit method allows you to increase the usability of these objects. Of course you get the full advantages (less dependency on the legacy classes) and disadvantages (additional objects) of a wrapper.
Here's a worked-up example in JAVA (because it is pretty strict, does not do double-dispatch by itself, and I'm quite familiar with it):
1) Your legacy Objects
Assuming you have your legacy objects Legacy1 and Legacy2which you cannot change, which have specific business methods:
public final class Legacy1 {
public void someBusinessMethod1(){
...
}
}
and
public final class Legacy2 {
public void anotherBusinessMethod(){
...
}
}
2) Prepare the Wrapper
You just wrap them in a VisitableWrapper which has a visit method that takes your visitor, like:
public interface VisitableWrapper {
public void accept(Visitor visitor);
}
With the following implementations:
public class Legacy1Wrapper implements VisitableWrapper {
private final Legacy1 legacyObj;
public Legacy1Wrapper(Legacy1 original){
this.legacyObj = original;
}
public void accept(Visitor visitor){
visitor.visit(legacyObj);
}
}
and
public class Legacy2Wrapper implements VisitableWrapper {
private final Legacy2 legacyObj;
public Legacy2Wrapper(Legacy2 original){
this.legacyObj = original;
}
public void accept(Visitor visitor){
visitor.visit(legacyObj);
}
}
3) Visitor, at the ready!
Then your own Visitors can be set to visit the wrapper like so:
public interface Visitor {
public void visit(Legacy1 leg);
public void visit(Legacy2 leg);
}
With an implementation like so:
public class SomeLegacyVisitor{
public void visit(Legacy1 leg){
System.out.println("This is a Legacy1! let's do something with it!");
leg.someBusinessMethod1();
}
public void visit(Legacy2 leg){
System.out.println("Hum, this is a Legacy 2 object. Well, let's do something else.");
leg.anotherBusinessMethod();
}
}
4) Unleash the power
Finally in your code, this framework would work like this:
public class TestClass{
// Start off with some legacy objects
Legacy1 leg1 = ...
Legacy2 leg2 = ...
// Wrap all your legacy objects into a List:
List<VisitableWrapper> visitableLegacys = new ArrayList<>();
visitableLegacys.add(new Legacy1Wrapper(legacy1));
visitableLegacys.add(new Legacy2Wrapper(legacy2));
// Use any of your visitor implementations!
Visitor visitor = new SomeLegacyVisitor();
for(VisitableWrapper wrappedLegacy: visitableLegacys){
wrappedLegacy.accept(visitor);
}
}
The expected output:
This is a Legacy1! let's do something with it!
Hum, this is a Legacy 2 object. Well, let's do something else.
Drawbacks:
Quite a lot of boilerplate. Use Lombok if you develop in Java.
Quite a lot of wrapper objects instances. May or may not be a problem for you.
You need to know the specific type of the objects beforehand. This implies you know their subtype, they aren't bundles in a List. If that's the case, you have no other option but to use reflection.
There should be a possibility to add new functionality to the classes of some hierarchy, without changing the base class interface. Kinds of possible behavior should be constant, while operations for different classes should execute differently.
The Visitor Pattern allows to concentrate all that operations in one class. There might be a lot of Concrete Element classes (from the diagram), but for each of them there will be implemented visit() method in Concrete Visitor class that will define his own algorithm.
Definition and implementation of method for each subclass of Element class:
public interface Visitor {
void visit(Element element);
}
public class ConcreteVisitor implements Visitor {
public void visit(Element element) {
// implementation
}
}
The Visitor Pattern is easily extended for new operations by implementing this interface by new class with his method implementation.
The following structure encapsulates the Element class:
public lass ObjectStructure {
private Element element;
// some methods
}
This ObjectStructure class could aggregate one or several instances of Element. Presentation that Visitor acts on:
public interface Element {
void accept(Visitor visitor);
}
And implementation of accept() method in the concrete entity:
public class ConcreteElement implements Element {
public void accept(Visitor visitor) {
visitor.visit();
}
}
Using of Visitor Pattern allows to save Element hierarchy from huge logical functionality or complicated configuration.
It is desirable to add the functionality to all the classes of hierarchy while defining a new Visitor subclasses. But there could be a problem: visit() should be overriden for every hierarchy type. To avoid this it's better to define AbstractVisitor class and all leave his all visit() method bodies empty.
Conclusion: using this pattern is good when class hierarchy of type Element keeps constant. If new classes add, it usually goes to considerable changes in classes of Visitor type.
My answer is very similar to Michael von Wenckstern's, with the improvements that we have a named accept method (more like the standard pattern) and that we handle unknown concrete classes -- there's no guarantee that at some point a concrete implementation we haven't seen before won't appear on the classpath.
My visitor also allows a return value.
I've also used a more verbose name for the visit methods -- including the type in the method name, but this isn't necessary, you can call them all visit.
// these classes cannot be modified and do not have source available
class Legacy {
}
class Legacy1 extends Legacy {
}
class Legacy2 extends Legacy {
}
// this is the implementation of your visitor
abstract class LegacyVisitor<T> {
abstract T visitLegacy1(Legacy1 l);
abstract T visitLegacy2(Legacy2 l);
T accept(Legacy l) {
if (l instanceof Legacy1) {
return visitLegacy1((Legacy1)l);
} else if (l instanceof Legacy2) {
return visitLegacy2((Legacy2)l);
} else {
throw new RuntimeException("Unknown concrete Legacy subclass:" + l.getClass());
}
}
}
public class Test {
public static void main(String[] args) {
String s = new LegacyVisitor<String>() {
#Override
String visitLegacy1(Legacy1 l) {
return "It's a 1";
}
#Override
String visitLegacy2(Legacy2 l) {
return "It's a 2";
}
}.accept(new Legacy1());
System.out.println(s);
}
}
First I had to made a few assumptions about the legacy code, since you didn't provide much details about it. Let's say I need to add a new method to Legacy without reimplementing everything. This is how I'll do it:
public interface LegacyInterface {
void A();
}
public final class LegacyClass implements LegacyInterface {
#Override
public void A() {
System.out.println("Hello from A");
}
}
First extends the "contract"
public interface MyInterface extends LegacyInterface {
void B();
}
And implement it in a "decorated" way
public final class MyClass implements MyInterface {
private final LegacyInterface origin;
public MyClass(LegacyInterface origin) {
this.origin = origin;
}
#Override
public void A() {
origin.A();
}
#Override
public void B() {
System.out.println("Hello from B");
}
}
The key point is MyInterface extends LegacyInterface: this is the guarantee the implementations will benefit from both the services from the legacy code and your personnal addings.
Usage
MyInterface b = new MyClass(new LegacyClass());
I think the best approach is the Option 1: Extend one more inheritance hierarchy on top of third party class and implement the visitor pattern with double dispatch.
The problem is the number of additional classes you need, but this can be resolved with a dynamic wrapper decorator.
The Wrapper Decorator is a way to add interface implementation, methods and properties to already existing obejcts: How to implement a wrapper decorator in Java?
In this way you need your Visitor interface and put there the visit(L legacy) methods:
public interface Visitor<L> {
public void visit(L legacy);
}
In the AcceptInterceptor you can put the code for the accept method
public class AcceptInterceptor {
#RuntimeType
public static Object intercept(#This WrappedAcceptor proxy, #Argument(0) Visitor visitor) throws Exception {
visitor.visit(proxy);
}
}
The WrappedAcceptor interface defines the method to accept a visitor and to set and retrieve the wrapped object
interface WrappedAcceptor<V> {
Object getWrapped();
void setWrapped(Object wrapped);
void accept(V visitor);
}
And finally the utility code to create the Wrapper around any obect:
Class<? extends Object> proxyType = new ByteBuddy()
.subclass(legacyObject.getClass(), ConstructorStrategy.Default.IMITATE_SUPER_TYPE_PUBLIC)
.method(anyOf(WrappedAcceptor.class.getMethods())).intercept(MethodDelegation.to(AcceptInterceptor.class))
.defineField("wrapped", Object.class, Visibility.PRIVATE)
.implement(WrappedAcceptor.class).intercept(FieldAccessor.ofBeanProperty())
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
WrappedAcceptor wrapper = (WrappedAcceptor) proxyType.newInstance();
wrapper.setWrapped(legacyObject);
If your library does not has accept methods you need to do it with instanceof. (Normally you do twice single-dispatching in Java to emulate double dispatching; but here we use instanceof to emulate double dispatching).
Here is the example:
interface Library {
public void get1();
public void get2();
}
public class Library1 implements Library {
public void get1() { ... }
public void get2() { ... }
}
public class Library2 implements Library {
public void get1() { ... }
public void get2() { ... }
}
interface Visitor {
default void visit(Library1 l1) {}
default void visit(Library2 l2) {}
default void visit(Library l) {
// add here instanceof for double dispatching
if (l instanceof Library1) {
visit((Library1) l);
}
else if (l instanceof Library2) {
visit((Library2) l);
}
}
}
// add extra print methods to the library
public class PrinterVisitor implements Visitor {
void visit(Library1 l1) {
System.out.println("I am library1");
}
void visit(Library2 l2) {
System.out.println("I am library2");
}
}
and now in any method you can write:
Library l = new Library1();
PrinterVisitor pv = new PrinterVisitor();
pv.visit(l);
and it will print to you "I am library1";
I would like to use the builder pattern in some upcoming work that I have which has several classes in a hierarchy. The base class will have at least 9 fields to start, and the various sub-classes may add between 2-4 more fields each. This would get out of hand very quickly and the builder pattern is appealing to me for this exact reason. I got some initial exposure to the builder pattern in books and articles. They were helpful, but had nothing on how to extend this pattern. I tried to implement this by myself, but I ran into trouble with the constructors of each of the sub-classes because I didn't get how to pass the collected data in the builder to super class. I looked on SO for some answers, and here's what I found.
This one is from SO 24243240 where an example of how to extend an abstract class with an abstract builder is given. It is also based on this blog post.
public abstract class AbstractA {
protected String s;
protected int i;
protected AbstractA() {
}
protected abstract static class ABuilder<T extends AbstractA, B extends ABuilder<T,B>> {
protected T object;
protected B thisObject;
protected abstract T getObject(); //Each concrete implementing subclass overrides this so that T becomes an object of the concrete subclass
protected abstract B thisObject(); //Each concrete implementing subclass builder overrides this for the same reason, but for B for the builder
protected ABuilder() {
object = getObject();
thisObject = thisObject();
}
public B withS(String s) {
object.s = s;
return thisObject;
}
public B withI(int i) {
object.i = i;
return thisObject;
}
public T build() {
return object;
}
}
}
public final class ConcreteA extends AbstractA {
private String foo;
protected ConcreteA() {
}
public static final class Builder extends AbstractA.ABuilder<ConcreteA,Builder> {
#Override protected ConcreteA getObject() {
return new ConcreteA();
}
#Override protected Builder thisObject() {
return this;
}
public Builder() {
}
public Builder withFoo(String foo) {
object.foo = foo;
return this;
}
}
}
And then in client code, it would look like...
ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();
I like this example because it allows you to easily extend these classes, but it also seems to me that this defeats the purpose of using the builder pattern because the methods withS(String s) and withI(int i) act alot like setter methods. Also, this method leaves the fields of the base class and the builder class as protected rather than private.
Here's one from SO 17164375
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
I like that this one seemingly adheres more closely to the builder pattern described by Josh Bloch and it also allows you to simply pass the builder into the constructor for the class you want to instantiate. This would be a nice way to do some validation inside the builder before instantiating the object in the call to build(). At the same time though, this example shows how you can extend the builder pattern with concrete classes, and when you do that the potential for all the nastiness that comes with extending concrete classes (e.g. inconsistent interfaces, inheriting methods which can corrupt the state of your object, etc.)
So my question is there a way to implement an abstract class with an abstract builder that also allows you to pass in a reference to a builder in the constructor for the base class? Something like:
public abstract BaseClass {
// various fields go here
...
public abstract Builder<T extends BaseClass, B extends Builder<T,B>> {
// add chaining methods here
...
public T build() {
if (isValid()) return new T(this);
else Throw new IllegalArgumentException("Invalid data passed to builder.");
}
}
public BaseClass(Builder builder) {
// set fields of baseclass here
}
}
I realize that you can't instantiate an object the way that I've shown here, but is there some other way to do it I mean? Is this possibly where a factory would go? Maybe I just have the wrong assumptions about the builder pattern in general. :) If that's the case, is there a better direction to take?
Your first example is not bad, but I don't think it is what you are looking for.
I am still a little unsure of exactly what you want, but seeing your examples do not work for you, I thought I'd give you one or two of my own. :)
class ParentBuilder{
public ConcreteParent build(){
ConcreteParent parent = new ConcreteParent();
parent.setFirst(1);
parent.setSecond(2);
parent.setThird(3);
return parent;
}
}
class ChildBuilder{
public ConcreteChild build(ParentBuilder parentBuilder){
ConcreteParent parent = parentBuilder.build();
ConcreteChild child = new ConcreteChild();
child.setFirst(parent.getFirst());
child.setSecond(parent.getSecond());
child.setThird(parent.getThird());
child.setFourth(4); //Child specific value
child.setFifth(5); //Child specific value
return child;
}
}
Any new type, would have its own builder, taking in its parent's builder.
As you can see this is similar to:
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
In your example.
This however, quickly gets out of hand as well, increasingly for the number of variables and subclasses.
An alternativ, would be to use dynanic variables, have a look at this: http://martinfowler.com/apsupp/properties.pdf
Martin Fowler writes a great article specifying all the pros and cons.
Anyways, here's my second example:
public class Demo {
public static void main(String[] args) {
ConcreteBuilder builder = new ConcreteBuilder();
Concrete concrete = builder.with("fourth", "valueOfFourth").build();
for(String value : concrete.getAttributes().values())
System.out.println(value);
}
}
class ConcreteBuilder{
private Concrete concrete;
public ConcreteBuilder(){
concrete = new Concrete();
}
public ConcreteBuilder with(String key, String value){
concrete.getAttributes().put(key, value);
return this;
}
public Concrete build(){
return concrete;
}
}
class Concrete{
private HashMap<String, String> attributes;
public Concrete(){
attributes = new HashMap<>();
}
public HashMap<String, String> getAttributes(){
attributes.put("first", "valueOfFirst");
attributes.put("second", "valueOfSecond");
attributes.put("third", "valueOfThird");
return attributes;
}
}
The magic here is, you (might) no longer need all these subclasses.
If these subclasses' behavior does not change, but only their variables, you should be fine using a system like this.
I strongly advise that you read Martin Fowler article on the subject though, there are good places and bad places to do this, but I think this is a good one.
I hope this brings you closer to an answer, good luck. :)
Please notice the updates, my question was not clearly formulated. Sorry for that.
Let us assume we have the following code:
class Foo extends/implements AnAbstractClass/AnInterface { /* to make sure the constructor with int as input is implemented */
Foo(int magicInt) { magicInt + 1; /* do some fancy calculations */ }
}
class Bar extends/implements AnAbstractClass/AnInterface { /* to make sure the constructor with int as input is implemented */
Bar(int magicInt) { magicInt + 2; /* do some fancy calculations */ }
}
class Factory<T extends/implements AnAbstractClass/AnInterface> {
int magicInt = 0;
T createNewObject() {
return new T(magicInt) // obviously, this is not working (*), see below
}
}
/* how it should work */
Factory<Foo> factory = new Factory<Foo>();
factory.createNewObject() // => Foo with magicInt = 1
Factory<Bar> factory = new Factory<Bar>();
factory.createNewObject() // => Bar with magicInt = 2
At position (*) I don't know what to do. How can I make sure, that the constructor with a signature like this ...(int magicInt) is implemented? I cannot define
a constructor with a certain signature in an interface
interface AnInterface {
AnInterface(int magicInt);
}
an abstract class enforcing a certain constructor
abstract class AnAbstractClass {
abstract AnAbstractClass(int magicInt);
}
and this is obviously missing the requirement of an implemented constructor in the subclasses:
abstract class AnAbstractClass {
AnAbstractClass(int magicInt) {}
}
a static method within an interface or abstract class, which can be overridden for each implementation of AnInterface or AnAbstractClass (I think of a factory pattern)
What is the way to go?
I really don't see your idea working.
I feel it breaks the concept of the Factory pattern, which really aims at having a method responsible for creating instances of a single class see ref.
I would rather:
have one method in your factory class for each type of object you want to construct
and possibly instead of having the specific behaviour in constructors, have one common constructor in a parent abstract class and one abstract method that does the fancy computation (but that's really style preference).
Which would result in something along the lines of:
abstract class AbstractSample {
private int magicInt;
public AbstractSample(int magicInt) {
this.magicInt = magicInt;
}
protected int getMagicInt() {
return magicInt;
}
public abstract int fancyComputation();
}
public class Foo extends AbstractSample {
public Foo(int magicInt) {
super(magicInt)
}
public int fancyComputation() {
return getMagicInt() + 1;
}
}
public class Bar extends AbstractSample {
public Bar(int magicInt) {
super(magicInt)
}
public int fancyComputation() {
return getMagicInt() + 2;
}
}
public class SampleFactory {
private int magicInt = 0;
public Foo createNewFoo() {
return new Foo(magicInt);
}
public Bar createNewBar() {
return new Bar(magicInt);
}
}
Answer to the previous version of the question might be deleted if the updated answer satisfies the OP
It's definitely weird to have classes that both extend Sample and implement SampleFactory...
I would rather have something along the lines of:
class Sample {
protected Sample() { /* ... */ }
}
interface SampleFactory<T extends Sample> {
T createSample(final int i);
}
class AccelerationSample extends Sample {
public AccelerationSample(final int i) { /* do some fancy int calculations*/ }
}
class OrientationSample extends Sample {
private OrientationSample (final int i) { /* do some fancy int calculations*/ }
}
abstract class SampleSource<T extends Sample> {
int magicInt;
SampleFactory<T> sampleFactory;
T getCurrentSample() {
return sampleFactory.createSample(magicInt);
}
}
class AccelerationSampleSource extends SampleSource<AccelerationSample> {
SampleFactory<AccelerationSample> sampleFactory = new SampleFactory<> {
public AccelerationSample createSample(final int i) {
return new AccelerationSample(i);
}
}
}
class OrientationSampleSource extends SampleSource<OrientationSample> {
SampleFactory<OrientationSample> sampleFactory = new SampleFactory<> {
public OrientationSample createSample(final int i) {
return new OrientationSample(i);
}
}
}
It would be cleaner still to use named factories, such as
public AccelerationSampleFactory implements SampleFactory<AccelerationSample> {
public AccelerationSample createSample(final int i) {
return new AccelerationSample(i);
}
}
Which you could then use as
class AccelerationSampleSource extends SampleSource<AccelerationSample> {
SampleFactory<AccelerationSample> sampleFactory = new AccelerationSampleFactory();
}
It sounds like you're really looking for a solution to how to write a generic factory method without a bunch of if/else blocks and without writing one in each class. As such, consider using reflection as in the following code:
interface Interface {
}
class Foo implements Interface {
Foo(int magicInt) { magicInt = magicInt + 1; /* do some fancy calculations */ }
}
class Bar implements Interface {
Bar(int magicInt) { magicInt = magicInt + 2; /* do some fancy calculations */ }
}
class Factory<T extends Interface> {
int magicInt = 0;
public T createNewObject(Class<T> typeToMake) {
try {
T t = createNewObjectWithReflection(typeToMake);
return t;
} catch (Exception e) {
throw new RuntimeException("Construction failed!", e);
}
}
private T createNewObjectWithReflection(Class<T> typeToMake) throws Exception {
// find the constructor of type to make with a single int argument
Constructor<T> magicIntConstructor = typeToMake.getDeclaredConstructor(Integer.TYPE);
// call the constructor with the value of magicInt
T t = magicIntConstructor.newInstance(magicInt);
return t;
}
}
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Factory<Foo> fooFactory = new Factory<Foo>();
Foo foo = fooFactory.createNewObject(Foo.class);
System.out.println(foo);
Factory<Bar> barFactory = new Factory<Bar>();
Bar bar = barFactory.createNewObject(Bar.class);
System.out.println(bar);
}
}
You can run the demo at IDEOne here.
As you have noted, none of the 3 ideas in the question are supported (a constructor with a certain signature in an interface, an abstract class enforcing a certain constructor, or a static method within an interface or abstract class)
However, you can define an interface (or abstract class) that is a Factory for the type that you ultimately want.
public interface AnInterface {
int fancyComputation();
}
public interface IFooBarFactory<T extends AnInterface> {
T create(int magicNumber);
}
IFooBarFactory has 2 concrete implementations
public class BarFactory implements IFooBarFactory<Bar> {
public Bar create(int magicNumber) {
return new Bar(magicNumber);
}
}
public class FooFactory implements IFooBarFactory<Foo> {
public Foo create(int magicNumber) {
return new Foo(magicNumber);
}
}
Then use the strategy pattern (https://en.wikipedia.org/wiki/Strategy_pattern) to retrieve the correct factory. Then use this factory, which has a known interface, to manufacture your object with the correct value (and any additional values that are required to manufacture an object).
FooBarFactory fooBarFactory = new FooBarFactory();
IFooBarFactory<T> factory = fooBarFactory.createFactory(typeOfAnInterface);
T impl = factory.create(magicNumber);
With the conrete implementations
public class Bar implements AnInterface {
private final int magicInt;
public Bar(int magicInt) {
this.magicInt = magicInt;
}
public int fancyComputation() {
return magicInt + 2;
}
}
public class Foo implements AnInterface {
private final int magicInt;
public Foo(int magicInt) {
this.magicInt = magicInt;
}
public int fancyComputation() {
return magicInt + 1;
}
}
the following code:
public static void main(String ... parameters) {
test(Foo.class);
test(Bar.class);
}
private static <T extends AnInterface> void test(Class<T> typeOfAnInterface) {
T impl = createImplForAnInterface(typeOfAnInterface, 10);
System.out.println(typeOfAnInterface.getName() + " produced " + impl.fancyComputation());
}
private static <T extends AnInterface> T createImplForAnInterface(Class<T> typeOfAnInterface, int magicNumber) {
FooBarFactory fooBarFactory = new FooBarFactory();
IFooBarFactory<T> factory = fooBarFactory.createFactory(typeOfAnInterface);
T impl = factory.create(magicNumber);
return impl;
}
prints
Foo produced 11
Bar produced 12
This provides a number of benefits over a solution with introspection or static factories. The caller does not need to know how to manufacture any of the objects, nor is the caller required to know or care when method is the "correct" method to use in order to retrieve the correct type. All callers simply call the one public/known component, which returns the "correct" factory. This makes your callers cleaner because they are no longer tightly coupled to the concrete implementations of AnInterface for the types FooBar. They only need to be concerned with "I need an implementation of AnInterface, which consumes (or processes) this type." I know that this means you have two "factory" classes. One to retrieve the correct factory, and the other which is actually responsible for creating the concrete types Foo and Bar. However, you hide this implementation detail from the callers through an additional layer of abstraction (see the createImplForAnInterface method).
This approach will be particularly beneficial if you are generally using some form of dependency injection. My recommendation with correspond exactly to Guice's assisted inject (https://github.com/google/guice/wiki/AssistedInject) or a similar idea in Spring (Is it possible and how to do Assisted Injection in Spring?).
This means that you need to have several factory classes (or dependency injection binding rules for Guice) but each of these classes are small, simple, and easy to maintain. Then you write a small test that retrieves all classes that implement AnInterface and you verify that your component which implements the strategy-pattern has covered all cases (through reflection - I would use the Reflections class in org.reflections:reflections). This gives you a usable code-abstraction that simplifies the use of these objects by reducing redundant code, loosening a tight coupling of components, and not sacrificing polymorphism.
This might not be possible but I am trying to create a constructor that only classes that share a super class can access, almost a reverse logic of the protected modifier. I assume there is no modifier to accomplish this directly, but knowing what I am trying to accomplish, any suggestions?
public Account extends SomeEntity {
//default public
public Account() {
}
// I am wanting this constructor to be only available to sibling classes.
// (those that share the same super class )
<modifier> Account(Element accountElement) {
}
}
public Accounts extends SomeEntity {
private List<Account> accountList;
//default public
public Accounts() {
Account newAcct = new Account(element);
//looped loading up Generic list of Account
this.accountList.add(newAcct);
}
I am working with RESTful web services and building the Objects out of XML responses, the problem is if I GET a listing of accounts, to build that into a list of Account Objects I would have to query the web service for each individual account even though I already have the information, and that seems entirely inefficient.
BUT
I don't want to give a general user, of the API I'm building, to be able to instantiate an Account Object this way. (With an Element)
There is no language construct like this. Package (=default) access is the only Java mechanism in town, as of 1.6.
I'm sure you could do nasty things with the stack, but I wouldn't recommend them.
I'd take a look at the factory pattern. You can probably play games with the access modifiers of the factory method(s) to get something close to what you want. You might also be able to play with reflection inside the factory method to get something closer to what you want than what package access gets you.
Sorry but I still don't get the point of this design. If a method is added to a class, its implementation will probably use private data to this class only, and therefore no guarantee can be made to 'sibling' classes that this data is also available for them. In other words, if your wish was granted, how would you guarantee that constructor Account(Object arg0) implementation won't use private data to Account class? (and therefore invisible to Accounts class)
It seems to me like you desire your code to provide the same interface for a single account and a list of accounts - extending SomeEntity class. That can be accomplished more elegantly with a composite pattern.
http://en.wikipedia.org/wiki/Composite_pattern
if your intent however is to provide a custom constructor that only subclasses will use, why not declare the custom constructor in SomeEntity and making this class abstract?
also, remember you can do this:
public Account() {
this(new arg0());
}
Account(Object arg0) {
}
Not sure if this helps, though.
There is a way to emulate the C++'s friend feature, and thus achieve the result you want.
Warning: This is a contrived technique that should be used only if you have no other solution!
Since no modifier does what you want in this case, the trick is to move the access restriction to another place, where modifiers apply. To do that, add a key parameter to the constructor. That key is of a class that can only be instantiated by the allowed "sibling" classes, i.e. by the subclasses of a given class.
The restriction is thus moved to the common superclass, where restraining the creation of the key is possible with the usual modifiers.
Here is an example:
public class CommonSuperClass {
public static final class Key {
private Key() {}
}
// This is the only way to create a key, and it's protected
protected final Key createKey() {
return new Key();
}
}
public class Account {
// The restricted constructor can even be public
public Account(Key key) {
// Everybody can try with null, but we're not that stupid
// Of course any RuntimeException can be thrown instead
if (key == null) throw new UnsupportedOperationException();
}
}
public class AllowedSibling extends CommonSuperClass {
public void foo() {
// I'm allowed
new Account(this.createKey());
}
}
public class DeniedClass {
public void foo() {
// This doesn't compile
new Account(new Key());
// This will throw an exception
new Account(null);
}
}
This is a very strange requisite, and I think no access modifier can do what you want. Anyway, I recommend that you just make the constructors public and document them as "for internal use only".
If you really need to limit access you can use this wordy solution:
public class Base {
protected interface Factory {
Base getInstance(Element e);
}
private static Map<Class<?>, Factory> registry = new HashMap<Class<?>, Factory>();
protected static void register(Class<?> c, Factory f) { registry.put(c, f); }
protected static <T extends Base> T create(Class<T> c, Element e) {
return (T) registry.get(c).getInstance(e);
}
}
public class Derived1 extends Base {
protected Derived1(Element e) { }
private static class Derived1Factory implements Factory {
public Derived1 getInstance(Element e) {
return new Derived1(e);
}
}
static {
register(Derived1.class, new Derived1Factory());
}
}
public class Derived2 extends Base {
protected Derived2(Element e) { }
private static class Derived2Factory implements Factory {
public Derived2 getInstance(Element e) {
return new Derived2(e);
}
}
static {
register(Derived2.class, new Derived2Factory());
}
public void method() {
Element e = null;
...
// Put some element in e
...
// This is what you were trying to do
Derived1 d1 = create(Derived1.class, e);
}
}
public class SomeEntity
protected void init(Element accountElement) {}
public class Account extends SomeEntity
public Account()
....
protected void init(Element accountElement)
....
public class Accounts extends SomeEntity
Account newAcct = new Account();
newAcct.init(element);
Here's what I would try (I have not tested this method):
<modifier> Account(Object arg) {
if (!super.getClass().isAssignableFrom(this.getClass())) {
throw new AssertionError("This constructor is only available to super classes.");
} else {
// Continue...
}
}