Suppose you create a class names Person using the builder pattern, and suppose the Builder class contains methods body(), head(), arms() and of course build() and you consider methods head() and build() obligatory for the user of this class.
We would like to somehow mark these methods obligatory, if possible using annotations. If a user of this class tries to build a Person instance but forgot to call either of these methods, we would like to get some kind of warning - either from the java compiler, or maybe from Eclipse or Maven, which we use to build our projects - any of them would do.
Is it possible to do? Which way would you suggest?
Here is an example with using different types to make some parts mandatory (it also makes the order you call the methods mandatory):
package test;
import test.StepOne.StepThree;
import test.StepOne.StepTwo;
import test.StepOne.LastStep;
public class TestBuilder {
public static void main(String[] args) {
String person1 = PersonBuilder.newInstance().head("head").body("body").arm("arm").leg("leg").build();
String person2 = PersonBuilder.newInstance().head("head").body("body").arm("arm").build();
}
}
interface StepOne {
// mandatory
StepTwo head(String head);
interface StepTwo {
// mandatory
StepThree body(String body);
}
interface StepThree {
// mandatory
LastStep arm(String arm);
}
// all methods in this interface are not mandatory
interface LastStep {
LastStep leg(String leg);
String build();
}
}
class PersonBuilder implements StepOne, StepTwo, StepThree, LastStep {
String head;
String body;
String arm;
String leg;
static StepOne newInstance() {
return new PersonBuilder();
}
private PersonBuilder() {
}
public StepTwo head(String head) {
this.head = head;
return this;
}
public LastStep arm(String arm) {
this.arm = arm;
return this;
}
public StepThree body(String body) {
this.body = body;
return this;
}
public LastStep leg(String leg) {
this.leg = leg;
return this;
}
public String build() {
return head + body + arm + leg;
}
}
Edit
The OP was so impressed with this answer that he wrote it up fully in a blog. It's such a clever take on the builder pattern that a full treatment deserves to be referenced here.
I believe the correct use of the builder pattern would solve the issue you're having.
I would create class PersonBuilder which would contain the methods setBody() and setArms() and every other optional parameter setter method. The constructor of the builder would take the required parameters. Then the method build() would return the new instance of Person.
public class PersonBuilder
{
private final Head head;
private Body body;
private Arms arms;
public PersonBuilder(Head head)
{
this.head = head;
}
public void setBody(Body body)
{
this.body = body;
}
public void setArms(Arms arms)
{
this.arms = arms;
}
public Person build()
{
return new Person(head, body, arms);
}
}
Alternatively you could pass the Head parameter to the method build() but I prefer passing it in the constructor instead.
No way with the compiler.
You can do is throw a runtime exception from the build() method that the builder is not properly initialized (and have a test that is invoked in the maven test phase)
But you can also have build(..) accept a HeadDetails object. That way tou can't invoke build without specifying the obligatory parameters.
Why not calling body(), head(), arms() in the build()-Method if it is really mandatory and returning Person in the build() method?
[edit]
Short example:
public class Builder {
private final String bodyProp;
private final String headProp;
private final String armsProp;
private String hearProps;
public Builder(String bodyProp, String headProp, String armsProp) {
super();
this.bodyProp = bodyProp; // check preconditions here (eg not null)
this.headProp = headProp;
this.armsProp = armsProp;
}
public void addOptionalHair(String hearProps) {
this.hearProps = hearProps;
}
public Person build() {
Person person = new Person();
person.setBody(buildBody());
// ...
return person;
}
private Body buildBody() {
// do something with bodyProp
return new Body();
}
public static class Person {
public void setBody(Body buildBody) {
// ...
}
}
public static class Body {
}
}
Maybe inside of build() you could check if all the required methods have been called. Behaps the Person instance has some internal sanity check which is triggered by build().
Of course this checks runtime behaviour and is no static analysis as you describe it.
isn't possible to call these methods in Person's constructor ?
Related
Here is some part of the practice.
I created an abstract parent class called Equipment, which has four child classes as shown as ConcreteMixer. Then the exercise asked me to create a class named Job, in which its constructor is as shown in the figure. I can’t understand the meaning of the list parameter, but I still created a class according to its requirements, and set it in It is instantiated in the main function.
This is the result of instantiation. I don’t know what the result of this parameter instantiation has to do with Equipment and its subclasses
public abstract class Equipment {
String requirement;
public Equipment(String requirements){
this.requirement=requirements;
}
public String getRequirement() {
return requirement;
}
}
public class ConcreteMixer extends Equipment{
public ConcreteMixer(String requirement){
super(requirement);
}
public String toString(){
return requirement;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof ConcreteMixer) {
ConcreteMixer that = (ConcreteMixer) obj;
return this.requirement.equals(that.requirement);
} return false;
}
}
public Job(Address location, String description,List<Equipment> requiredEquipment, Date plannedDate) {
this.location = location;
this.description = description;
this.requiredEquipment = requiredEquipment;
this.plannedDate = plannedDate;
}
public static void main(String[] args) {
Job s= new Job(new Address("Star street",16, "da","London"),"mixer",new
ArrayList<Equipment>(),new Date(12,5,21));
System.out.println(s);
}
}
and this is the result for the main method
location:Address isLondonStar street16da
description:mixer
requiredEquipment:[]
plannedDate:day:12
month:5
year:21
As shown, your image shows nothing about using (or defining) your Equipment subclasses
But the point of the parameter is that the job can use multiple of any Equipment type
List<Equipment> e = new ArrayList<>();
e.add(new ConcreteMixer("concrete"));
Job j = new Job(..., e,...);
Yes, I read many examples in web, but I didn't find a way how to call a method based on string value. May be I am not searching in right way... I wrote all code, but don't know how to call the method.
fyi: I don't want to use if else or switch case
Here is what I want:
I get the card reader type as String from database. I have to call the corresponding class' method.
My code:
LoginPanel.java
public class LoginPanel {
public static void main(String args[]) {
String readerType = "Omnikey5427-CK"; // I get this ("Omnikey5427-CK" or "Omnikey5427-G2") from a database as String
// I WANT TO CALL getCardNumber() method of respective class
}
}
ISmartCardReader.java
public interface ISmartCardReader {
public Integer getCardNumber();
}
Omnikey5427G2.java
public class Omnikey5427G2 implements ISmartCardReader {
public Omnikey5427G2() {
System.out.println("G222222222222222...");
}
public Integer getCardNumber() {
return 222;
}
}
Omnikey5427CK.java
public class Omnikey5427CK implements ISmartCardReader {
public Omnikey5427CK() {
System.out.println("CKKKKKKKKKKKKKKK...");
}
public Integer getCardNumber() {
return 111;
}
}
SmacrtCardEnumFactory.java
public enum SmacrtCardEnumFactory {
OMNIKEY5427CK("Omnikey5427-CK") {
public ISmartCardReader geInstance() {
return new Omnikey5427CK();
}
},
OMNIKEY5427G2("Omnikey5427-G2") {
public ISmartCardReader geInstance() {
return new Omnikey5427G2();
}
};
private String cardReaderName;
private SmacrtCardEnumFactory(String cardReaderName) {
this.cardReaderName = cardReaderName;
}
public String cardReaderName() {
return cardReaderName;
}
}
You can use valueOf() function of enum provided your enum sonstant names match strings used to lookup (you may use cardName.toUpper()). You may also create objects for all the card types and store them in a hash map and then lookup them. You can also write some fatory method, but this will be if-then-else or switch inside
You could iterate over the factory's values() and get the one that matches the string:
public enum SmacrtCardEnumFactory {
// current code omitted for brevity
public static getSmartCardReader(String name) {
return Arrays.stream(values())
.filter(r -> r.cardReaderName().equals(name))
.map(SmacrtCardEnumFactory::getInstance();
.orElse(null);
}
}
I have this scenario. I started working with a system that 'process' documents. The problem is, it seems to be the typical scenario where it started small, and went getting bigger and bigger constructing it one chunk at a time and now it needs to be refactored.
Each document type has an identifier (docID), and all of them share the same underlying result structure.
There is a huge master class that does all the job BUT inside this class there are several methods (almost one for each site) with its own logic. They all do almost the same with slight changes (i.e. formatting a string before setting it to a field in the result structure or doing some calculation and then setting the field in the result structure).
For example:
private Result processDocGeneric(Result result){
result.setField1("value1");
result.setField2("value2");
result.setField3("value3");
return result;
}
private Result processDoc1(Result result){
result.setField1("VALUE1");
return result;
}
private Result processDoc2(Result result){
result.setField2("V-A-L-U-E-2");
return result;
}
private void processDocs(){
Result result = new Result();
result = processDocGeneric(result);
if(docID == 1){
result = processDoc1(result);
}
else if(docID == 2){
result = processDoc2(result);
}
...
}
Ok, so I'm planning to refactor this and I'm considering some design patterns I know but I don't want the feel that I'm killing a roach with a bazooka.
Command pattern is maybe the first that comes to my mind, also Strategy pattern. My major concern with those is that I will have to create a class for every document type that has its own implementation of the processDoc method (There are around 15 at the moment). I mean, if that's the way to go, that would be it but if there's a simpler way of doing it that I don't know, it would be better (since the change is in a single method).
The other thing that I could do is moving all those method to a 'methods' class, and also move the if-else block to a single method with a docID parameter (process(int docID) and then call it from the main class. But that's just splitting the huge class. It would be "cleaner" but not optimal.
What would be the best approach to clean and split this huge class and make it scalable (since there would be new document types to be added in the future)?.
You can use factory or abstract factory design patterns maybe, In this patterns you can get your needed objects without having to specify the exact class of the object that will be created.
I propose a solution based on the Visitable / Visitor Pattern. this solution requires very little change to the Result class, while opening the door to new visiting objects, making it an easily extensible framework. I'm making heavy use of Java8's default interface method.
The Visitor / Visitable Interfaces:
public interface DocVisitor<T extends VisitableDoc> {
default void visit(T document){
switch(document.getDocId()){
case 1:
processDoc1(document);
break;
case 2:
processDoc2(document);
break;
// ... other cases...
default:
processDocGeneric(document);
break;
}
}
void processDocGeneric(VisitableDoc document);
void processDoc1(VisitableDoc document);
void processDoc2(VisitableDoc document);
}
public interface VisitableDoc {
int getDocId();
default void visit(DocVisitor visitor){
visitor.visit(this);
}
}
Slight modification of the Result class:
public class Result implements VisitableDoc { // New interface declared
int getDocId(){
return docId; // This might already exist
}
// Rest is unchanged, the default implementation will suffice
}
A Visitor Implementation:
public class DocProcessor implements DocVisitor<Result> {
#Override
private Result processDocGeneric(Result result){
result.setField1("value1");
result.setField2("value2");
result.setField3("value3");
return result;
}
#Override
private Result processDoc1(Result result){
result.setField1("VALUE1");
return result;
}
#Override
private Result processDoc2(Result result){
result.setField2("V-A-L-U-E-2");
return result;
}
}
Usage:
public static final main(String[] args){
List<Result> results = // Obtain results somehow
DocProcessor processor = new DocProcessor();
for(Result result: results){
processor.visit(result);
}
}
[How to] split this huge class and make it scalable (since there would be new document types to be added in the future
What I've done is merely to split Document data on Result class / Document Processing on DocProcessor class. If you have other processing that differ from type to type, and which can be extracted to an external class (no need for private field handling, private methods calling etc.), this framework os completely applicable.
If not, you should REALLY consider refactoring it to use polymophism! Make each Document type its own object. Use a strong abstract class to link them all, and if you have many methods that are shared accross several but not all types, then make sub-types accordingly - or use default methods! Java8 FTW
For this situation is applicable builder pattern.
/**
*
* Hero, the class with many parameters.
*
*/
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
public Profession getProfession() {
return profession;
}
public String getName() {
return name;
}
public HairType getHairType() {
return hairType;
}
public HairColor getHairColor() {
return hairColor;
}
public Armor getArmor() {
return armor;
}
public Weapon getWeapon() {
return weapon;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("This is a ")
.append(profession)
.append(" named ")
.append(name);
if (hairColor != null || hairType != null) {
sb.append(" with ");
if (hairColor != null) {
sb.append(hairColor).append(' ');
}
if (hairType != null) {
sb.append(hairType).append(' ');
}
sb.append(hairType != HairType.BALD ? "hair" : "head");
}
if (armor != null) {
sb.append(" wearing ").append(armor);
}
if (weapon != null) {
sb.append(" and wielding a ").append(weapon);
}
sb.append('.');
return sb.toString();
}
/**
*
* The builder class.
*
*/
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
/**
* Constructor
*/
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
}
This is a continuation from what I was working in Passing 1 to many parameters of same object type
I've gotten good feedback on that , I believe i have the improved the design . The whole code is at https://github.com/spakai/flow_input_builder
The requirement is simple : -
I need to build a set of input for different workflows using 1 or more outputs from previous workflows
I have a set of interfaces
public interface SwfInput {
}
public interface SwfOutput {
}
public interface Workflow<I extends SwfInput, O extends SwfOutput> {
public O execute(I input);
}
public interface Builder<I extends SwfInput> {
public I build();
}
Now , Say I have 3 flows which gets executed in sequence FlowA->FlowB->FlowC
FlowC needs mandatory output from FlowB but only optionally from FlowA
so I have a implementation for FlowCBuilder
public class FlowCInputBuilder implements Builder<FlowCInput> {
private final FlowBOutput mandatoryflowBOutput;
private FlowAOutput optionalflowAOutput;
public FlowAOutput getOptionalflowAOutput() {
return optionalflowAOutput;
}
public FlowCInputBuilder setOptionalflowAOutput(FlowAOutput optionalflowAOutput) {
this.optionalflowAOutput = optionalflowAOutput;
return this;
}
public FlowCInputBuilder(FlowBOutput mandatoryflowBOutput) {
this.mandatoryflowBOutput = mandatoryflowBOutput;
}
#Override
public FlowCInput build() {
FlowCInput input = new FlowCInput();
input.setMandatoryFromFlowB(mandatoryflowBOutput.getOutput1FromB());
if (optionalflowAOutput != null) {
input.setOptionalFromFlowA(optionalflowAOutput.getOutput2FromA());
}
return input;
}
}
one test i have written shows an example usage
FlowBOutput mandatoryflowBOutput = new FlowBOutput();
mandatoryflowBOutput.setOutput1FromB("iNeedThis");
FlowAOutput optionalflowAOutput = new FlowAOutput();
FlowCInput input = new FlowCInputBuilder(mandatoryflowBOutput)
.setOptionalflowAOutput(optionalflowAOutput)
.build();
I have not used static inner class for the Builder pattern.
Any suggestions are welcomed.
You should use static inner class. The key point of using this approach is that, the inner can directly access private properties of the object being constructed. This helps eliminating duplicated code since the builder does not need to maintain a long list of temporary state for the constructing. So, your code can be rewritten like this:
public class FlowCInput {
private int output1FromB; // suppose that it is int
private String output2FromA; // suppose that it is String
private FlowCInput() { }
//...
public static class FlowCInputBuilder implements Builder<FlowCInput> {
private final FlowCInput result;
public FlowCInputBuilder(FlowBOutput mandatoryflowBOutput) {
result = new FlowCInput();
// output1FromB is private but still accessed from here
result.output1FromB = mandatoryflowBOutput.getOutput1FromB();
}
public FlowCInputBuilder setOptionalflowAOutput(FlowAOutput optionalflowAOutput) {
// same for output2FromA
result.output2FromA = optionalflowAOutput.getOutput2FromA();
return this;
}
#Override
public FlowCInput build() {
return result;
}
}
}
As you see, the builder now holds only a FlowCInput object, it does not unnecessarily hold mandatoryflowBOutput and optionalflowAOutput as before.
I have a class contains 10 methods which are doing almost the same things apart from one key event. Two examples are given below:
Public String ATypeOperation(String pin, String amount){
doSomething();
doMoreStuff();
requestBuilder.buildATypeRequest(pin, amount);
doAfterStuff();
}
Public String BTypeOperation(String name, String sex, String age){
doSomething();
doMoreStuff();
requestBuilder.buildBTypeRequest(name, sex, age);
doAfterStuff();
}
As you can see from the above methods, they are similar apart from calling different methods provided by requestBuilder. The rest 8 are similar too. There is a lot duplicated code here. I feel there is a better way to implement this, but don’t know how. Any ideas and suggestions are appreciated.
Thanks,
Sarah
Use something like RequestBuilder, that accepts all these kinds of parameters:
public RequestBuilder {
// setters and getters for all properties
public Request build() {
doStuff();
Request request = new Request(this);
doAfterStuff();
return request;
}
}
and then
new RequestBuilder().setAge(age).setName(name).build();
What’s the nearest substitute for a function pointer in Java?
Function Pointers in Java
interface RequestBuilder {
void doStuff(params);
}
public RequestBuilder getARequestBuilder() {
return new RequestBuilder() {
void doStuff(params) {
// impl.details
}
}
}
public RequestBuilder getBRequestBuilder() {
return new RequestBuilder() {
void doStuff(params) {
// impl.details
}
}
}
public String buildRequest(yourParams, RequestBuilder builder){
doBefore();
builder.doStuff(yourParams);
doAfter();
}
I think this is called the Strategy pattern. It looks a lot like the Command pattern but because you encapsulate an algorithm it seems to be Strategy :)
What Bozho suggest is the Builder pattern.
I recommend you browse through a list of patterns some time, or buy Head First Patterns. Really fun reading.
You could pass the builder object to a generic buildRequest method. Since not only the algorithm but also the arguments vary, i put them into the builder. I dont think thats a nice solution but i wanted to show a command pattern here :D (Extraneon showed how to decouple params and command)
// call somewhere in the code:
Builder b = new BTypeBuilder();
b.age = "20"; b.sex = "female"; b.name = "eve";
String res = buildRequest(b);
Public String buildRequest(Builder builder)
{
doSomething();
doMoreStuff();
builder.build();
doAfterStuff();
}
// Command pattern
class BTypeBuilder implements Builder
{
String name, age, sex;
// Constructor here
void build()
{
// Do your stuff here
}
}
class ATypeBuilder implements Builder
{
String pin, amount;
// Constructor here
void build()
{
// Do your stuff here
}
}
public interface Builder
{
void build();
}
In addition to other answers, this might also be useful for you (If you want to just plugin your method, not using your parameters for 'before' and 'after' methods)
interface Function0<R> {
R apply();
}
public void performOperation(Function0<Void> operation) {
doSomething();
doBeforeStuff();
operation.apply();
doAfterStuff();
}
then you could use it like this,
final RequestBuilder builder = new RequestBuilder();
performOperation(new Function0<Void>() {
public Void apply() {
builder.buildATypeRequest("1234", "2445");
return null;
}
});
performOperation(new Function0<Void>() {
public Void apply() {
builder.buildBTypeRequest("1234", "2445", "1234");
return null;
}
});
Instead of sending a long parameter list just push all the parameters in a map and send that map as argument.