The factory example
In this example we'll dynamically inject a single instance that will construct an Object for us. Using this method we can create a factory that is so easy to extend that you don't need to modify it to add functionality. In this example we'll have a couple different Objects we want to create in our factory, and for fun, they won't be related whatsoever.FirstObject.java public class FirstObject{ public String value; } SecondObject.java public class SecondObject{ public Integer intVal; }OK, we have two really simple objects that share no inheritance, and we'll have our factory create both of them; but our factory is actually going to ship the work off-shore, it will out source the work to specialized shops that we'll call ObjectBuilder.
public interface ObjectBuilder { Object build(String value); }We're providing it with some extra information just so that we can see it do more than just create a new instance. These builders will be simple to write and here they are:
FirstObjectBuilder.java public class FirstObjectBuilder implements ObjectBuilder{ public Object build(String value) { FirstObject object = new FirstObject(); object.value = value; return object; } } SecondObjectBuilder.java public class SecondObjectBuilder implements ObjectBuilder{ public Object build(String value) { SecondObject object = new SecondObject(); object.intVal = Integer.parseInt(value); return object; } }Finally, before we get to making our factory we need a Qualifier. This qualifier will allow us to inject the specific ObjectBuilder that we want.
@Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER}) public @interface BuilderFor { Class value(); }We also need an Annotation Literal that we can manipulate during the CDI look-up.
public class BuilderForLiteral extends AnnotationLiteralThe annotation literal provides a "physical" object that we can manipulate programmatically to represent what we're looking for.implements BuilderFor{ private Class clazz; public BuilderForLiteral(Class clazz) { this.clazz = clazz; } public Class value() { return clazz; } }
Now that everything is in place, lets play with Instance and make our factory.
public class MyFactory{ ... }The first thing we need in our factory is an Instance, so we'll inject that.
@Inject @Any InstanceNext, lets define our method for building:objectBuilderInstances;
public Object build(Class typeToBuild, String value){ ... }Now, we're going to add a qualification to our Instance. This will limit the look-up to the specific ObjectBuilder we're looking for.
BuilderForLiteral builderForQualifier = new BuilderForLiteral(typeToBuild); InstanceSo, we now have a qualified Instance... great... we still don't have the object. But don't worry, that's the next step.qualifiedInstance = objectBuilderInstances.select(builderForQualifier);
ObjectBuilder builder = qualifiedInstance.get();We've now injected our ObjectBuilder programmatically, the rest is pretty straight-forward.
return builder.build(value);And the Factory class altogether looks like this:
public class MyFactory { @Inject @Any InstanceThis is a very powerful pattern that you can use throughout your applications, and this is just one example of using the Instance interface. Soon I'll post again about using the Instance interface to access multiple instances.objectBuilderInstances; public Object build(Class typeToBuild, String value){ BuilderForLiteral builderForQualifier = new BuilderForLiteral(typeToBuild); Instance qualifiedInstance = objectBuilderInstances.select(builderForQualifier); ObjectBuilder builder = qualifiedInstance.get(); return builder.build(value); } }
I once again want to say that this code is not production ready. For example, before we get the ObjectBuilder you should check to see if the Instance is unsatisfied or ambiguous and throw an Exception. You can use
qualifiedInstance.isUnsatisfied()
and qualifiedInstance.isAmbiguous()
to do this.
I hope you've enjoyed this post and come back again later for more.
No comments:
Post a Comment