Understanding the Builder/Factory Pattern - java

I'm trying to clean up some code I have written for reading data. I have two sources of data: a database and a file. Both currently have separate classes and both classes have optional, non common, parameters in the constructors provided (at the moment traditional telescoping constructors).Both classes Implement interface MyData and when I instantiate the objects I always instantiate a MyData object.
I want to merge these classes into a single class and make the instantiation as clean as possible but I can't figure out how. Im certain its a mixture of builder and factory patterns.The user should never have to see the underlying type MyDatabaseData and MyFileData, just MyData. Can someone help me by sketching out a similar example just to set me off in the right direction

Keep the classes separate since they do different things. Combining them will only make a giant mess and violates the Single Responsibility Principle.
If you don't want the users to see the classes, then make the classes package private.
Then you make a new Builder or Factory class that takes parameters and figures out which class to instantiate.
Hope this helps.

A builder pattern would look like this:
MyDatabaseData data = MyDatabaseData.create()
.authenticate("admin", "rumpelstielchen")
.get();
public class MyDatabaseData {
private MyDatabaseData() { }
public static MyDatabaseBuilder create() {
return new MyDatabaseBuilder(new MyDatabaseData());
}
}
public class MyDatabaseBuilder {
private MyDatabaseData data;
MyDatabaseBuilder(MyDatabaseData data) {
this.data = data;
}
public MyDatabaseData get() {
return data; // Do checks and yield the final result
}
public MyDatabaseBuilder authenticate(String user, String password) {
...
return this; // For chaining calls
}
}
Whether to use common base classes/interfaces is a matter of suitability:
public class MyDatabaseBuilder extends MyBuilder<MyDatabaseData>
However you will probably need to do specific things and hence need child classes. Development not necessarily will become easier, maintaining 4 classes with parallel evolutions.

Related

Avoid duplicate code with numerous Java classes sharing fields

I'm working on an application which writes on a NoSQL database (Elasticsearch to be precise) and I have to manage more than a dozen (the number grows with time) different document classes, that is classes with numerous fields, their getters and setters and methods to convert the class to a JSONObject (each field is annotated with #JsonProperty(PROPERTY_NAME) and we use a JSON parser ).
All these classes have some fields and methods in common, which are all contained in a superclass (let us call it DocZero) but they all have their own custom fields, which brings me to the point.
It is true that these fields are custom, but some are shared between different classes in a non-linear way, that is I have my document classes Doc1, ... DocN and I have some sets of fields (around 10 as of right now) shared by them in a very wild way.
Some examples to best convey the situation:
Doc1 contains Set1 to Set5;
Doc2 contains Set1, Set2 and Set5 to Set8;
Doc3 contains Set6 and Set7;
Doc4 contains Set5 and Set7;
Doc5 contains Set1, Set2, Set5 and Set7 to Set10.
Given that I need to get and set these fields and, from time to time, manipulate a document with them, I made interfaces out of the Set#, each containing (abstract) setters and getters.
As such, when I declare a class
public class DocX implements SetA, SetB, SetC
I get reminded to implement the methods and hence add the required fields, but this means that all the classes implementing the same set will need to have the same parameters and the same methods which means that I need to write the same code many times (sometimes more than getter and setter methods).
Adding all the fields to DocZero foregoing the different Doc# classes is a solution which I am not keen on using, since I prefer to distinguish different document types and since this situation is present, in lower magnitude, in another section of the code, with AnotherDocZero, AnotherDoc# and AnotherSet# for which merging cannot be done due to other constraints and for which I would like a potential solution to work too.
I feel like this is one of those situation where multiple inheritance would solve the issue, but unfortunately Java doesn't allow it.
How could I avoid duplication in a situation like this? Have you got any advice to improve my handling of this issue?
If several kinds of fields are often grouped together, that suggests that grouping is a natural part of the domain of your program, and should be represented as such.
So, if you often find this in your classes
int xCoordinate;
int yCoordinate;
You should instead introduce
public final class Point ... {
private final int x;
private final int y;
Point(int x, int y) {
...
}
...
}
then instead of repeating x and y, write
Point position;
I strongly suggest to keep your data classes simple even if it does mean that you will need to repeat many fields definitions - POJOs are definitely easier to maintain and understand how the "result" data object looks like if you have all fields in one place - multilevel inheritance will quickly create a mess
For constraints of having proper getters you should use interfaces as you do. You can even create single interface for every getter and group them in another one like
public interface Set1To5 extends Set1, Set2, Set3, Set4, Set5 {}
For avoid duplication of getters/setters you can use some additional lib like lombok or consider not using getters/setters at all (just make all the fields in your data document classes public - but this one of course is not the option if you need to constraint classes with interfaces)
There is a pattern to explore. I don't know it already exists or there is a specific name for it.
Consider:
Java 8+ interfaces can have default methods. These methods can use other interface methods to define additional / default logic. The class implementing such an interface automatically get these methods, without having to implement them.
Also, a class can implement multiple interfaces.
The above two can be used to have "easy to compose" types in Java.
Example:
Create a base interface that can store/retrieve data. This can be as simple as:
public interface Document {
<T> T get(String key);
void set(String key, Object value);
}
This is the basic capability that will be used by all specific data objects.
Now, define two interfaces that contain nothing but specific field getter/setters using the above interface:
public interface Person extends Document {
default String getName(){
return get("name");
}
default void setName(String name){
set("name", name);
}
}
And another one:
public interface Salaried extends Document {
default double getSalary(){
return get("salary");
}
default void setSalary(double salary){
set("salary", salary);
}
}
Get the idea? This is a simple schema built upon the basic get/set capability. And you might want to define field names as constants in real applications.
But so far, it is all interfaces. It is not linked to something real, like a DB. Hence we must define an implementation to Document that uses a DB storage:
public class DBDoc implements Document {
private final Map<String,Object> data;
public DBDoc(HashMap<String, Object> data) {
this.data = new HashMap<>(data);
}
public DBDoc(){
this.data = new HashMap<>();
}
#Override
#SuppressWarnings("unchecked")
public <T> T get(String key) {
return (T) this.data.get(key);
}
#Override
public void set(String key, Object value) {
this.data.put(key, value);
}
}
We have used a simple map for storage, but it might as well be using a db connection or db specific document to get/set data. This is up to what DB or storage you are using.
Finally, we have the capability to compose types out of these interfaces:
public class Employee extends DBDoc implements Person, Salaried { }
And use them:
public static void main(String[] args) {
Employee employee = new Employee();
employee.setName("Joe");
employee.setSalary(1000.00);
System.out.println(employee.getName());
System.out.println(employee.getSalary());
}
I think default method is an option to go.
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Counter of interface objects in Java

In Java, if I want to know how many object of type MyClass, i can define the MyClass in this way
public class MyClass {
public static int count = 0;
public MyClass() {
count++;
}
//other stuff
//...
}
and then, just calling
MyClass.count
I can get the number of objects created.
I am wondering if there's a way to do the same thing with an interface, e.g. if I have my interface called ICountable, how can I know how many objects that are ICountable are there in my program at that moment. I am thinking of doing this with a factory pattern, but in any design way I notice weaknesses, so I haven't come up to a working solution yet, does anyone know a good way to do this?
You could have a look at this thread:
how many instances for a class exists at runtime in java
But I recommend, that you do not implement such a mechanism. There is practically no use case for it in release code. And for debugging / profiling there are several tools. If I remember correctly, the Eclipse profiler keeps track of the instances out of the box, just start it and watch.
Refering to my answer in Get Member/Fields of an existing Object as faar as i know there is no way to guarantee getting all of such informations without parsing the classpath on the file to analyse any .class files or (e.g. static code analysis).
Even if there are classes implementing the desired interface those classes may not be directly visible/ accessable by your Classloaders (anonymous classes for example).
Still in my anser there is a library mentioned that most of the times does the job.
There can be several implementation for single interface. All implementation should consider as type of that interface.
You can try something similar to this.
My interface
public interface Val {}
Implementations
public class Impl1 implements Val {
public Impl1(){
Con.count++;
}
}
.
public class Impl2 implements Val {
public Impl2(){
Con.count++;
}
}
You need to use a global counter here.
Eg:
public final class Con {
static int count;
}
Now any time you can find the count of Val
public static void main(String[] args) {
new Impl1();
System.out.println(Con.count);
new Impl2();
System.out.println(Con.count);
}
you can use separate variables in Impl1 and Impl2 to count each of them separately too.

How do I create a Builder that can build more than one kind of Java object?

I’m trying to create a kind of Multi Strategy Builder. I mean this builder should be generalized and should have different method depends on entity type. Let me explain it.
Depends on entity we need to have different methods. Examples:
Builder<User> userBuilder;
userBuilder.withName(«Bob»);
userBuilder.withAge(17);
and this builder must have no others method!
Builder<Account> accountBuilder;
accountBuilder.withCounry(«Fr»);
accountBuilder.withNumber(2846218354);
accountBuilder.withCode(«X34»);
What pattern should I use? And how to organize my design?
If you're asking for a single Builder type that doesn't need to know anything about the entities it operates on, Java can't easily do it the way you describe. In the Builder<User> example, the withName and withAge methods would need to be known at compile-time.
Since those methods don't actually exist, but would need to be dynamically added, you'd have to write a custom class-loader. Once the Builder class is linked, you can't change it, and since it doesn't know what methods you want until you pass in an entity, it's too late to change at the point you need to add methods.
You could get mostly there by using reflection. For instance, you could have a single method in Builder called, say, with(String field, Class<?> c, Object value). Then, assuming the object instance you're building has a method named "set___", you can use the Method class to invoke the corresponding set method with the value that was passed in.
That would look something like:
Builder<Account> b = new Builder<>();
b.with("AccountNumber", String.class, "5897-1048-2949");
// this invokes "setAccountNumber" method on internal
// Account instance with "5897-1048-2949" cast to String
A better idea is to have classes for thing you're going to build: AccountBuilder, UserBuilder, and so on. This is clearer and is probably the best you can do in Java without resorting to exotic solutions like custom class-loaders. (Yes, you'll have to write the properties for each one.)
But if you decide you need to do a lot of building, you may want to consider an alternative language that makes this easier to pull off, like Ruby or Elixir. Dynamic methods are not Java's strong suit, and trying to circumvent a language's limitations just to achieve a particular API is generally a terrible idea.
It's not possible for generic interface to have different methods depending on passed to it class in Java. This means that Builder interface can have either:
withName and withAge methods
withCountry, withNumber and withCode methods
all of them
There is no design pattern that can overcome Java language limitations. What I would advise is to have generic builder interface like:
public interface Builder<T> {
T build();
}
and then create separate subclasses for each entity type:
public class UserBuilder implements Builder<User> {
public void withName(String name) {
// ...
}
public void withAge(int age) {
// ...
}
public User build() {
User user = new User();
user.setName(...);
user.setAge(...);
return user;
}
}
public class AccountBuilder implements Builder<Account> {
public void setCountry(String country) {
// ...
}
public void setNumber(String number) {
// ...
}
public void setCode(String code) {
// ...
}
public Account build() {
Account account = new Account();
account.setCountry(...);
account.setNumber(...);
account.setCode(...);
return account;
}
}
and then use it like
UserBuilder userBuilder = new UserBuilder();
userBuilder.setName("John");
userBuilder.setAge(20);
User user = userBuilder.build();
AccountBuilder accountBuilder = new AccountBuilder();
accountBuilder.setCountry("UA");
accountBuilder.setNumber("333-22-1");
accountBuilder.setCode("123");
And that's it. This can be slightly improved by using Fluent Interface pattern but anyway in Java it's impossible to implement it to work exactly like in your question.
Hope this helps...
First, adding dynamic methods is not very java like.
Builder is a creational pattern and strategy is behavioural. I would not mix them here.
Builder will create objects of a given TYPE. Do your USER and Account have a same type? IMO, unlike other design patterns books, the GoF book very effectively explains what a type of an object is. Do read the discussion. Given the code snippets, I wouldn't say user and account have same type. I would use different builders for building the objects of user and account. The type discussion will come in handy for strategy as well.

Grouping together "main" methods and their "helper" methods in Java

Avoiding large, monolithic methods is considered a good practice. I, personally, like to identify all pieces of code that serve a unique, unambiguous purpose and refactor them into a method. This way, the code reads more like a book.
The obvious problem with this approach is that my class ends up having a large number of methods available outside their intended scope, which I find highly undesirable.
There are ways to create nested functions in Java, but since the feature is not directly supported by the language, the resulting code is generally unfathomably ugly --at least, to me.
One could also use nested classes. What I don't like about this solution is that it's somewhat clumsy --is it?-- when some of the involved methods in the "grouping together" are overridden methods.
Rather vague question, but anyway I'd like to know how people go about doing this.
EDIT: Example of what I mean:
public class ClassWithTwoMainMethods {
private int var1;
private int var2;
public void doSomething(int a) {
if (conditionToCheck(a)) {
doSomethingSpecific();
}
}
private void doSomethingSpecific() {
...
}
private boolean conditionToCheck(int a) {
...
}
public void doSomethingElse(int a, int b) {
doSomethingElseHelper1(a+b);
doSomethingElseHelper2();
doSomethingElseHelper3();
}
private void doSomethingElseHelper1(int arg) {
...
}
private void doSomethingElseHelper2() {
...
}
private void doSomethingElseHelper3() {
...
}
}
At first glance, it isn't obvious that the class above has one "main" method with two "helpers" that should not be used anywhere else, and another "main" method with three helpers.
I use "worker objects" for this. A worker object exists only inside of a method and helps to achieve a goal. A typical example for this is String except that this worker is so useful that methods often return it.
So what I do is I group methods in a worker object, create it in a public API method (i.e. something is supposed to be used and documented in the public API) and let it do it's thing:
public void doSomethingElse(int a, int b) {
new Worker( a, b ).run();
}
This approach has some benefits:
You can test those workers in isolation.
It keeps code together that belongs together
It helps to avoid cluttering the namespace of a class. It does pollute the global namespace somewhat, though.
It allows you to reuse workers in different classes.
I can lessen the restrictions on fields for workers. For main classes, I prefer fields that don't change. In workers, fields are often more like local variables. That way, I can reduce the number of method parameters but I need to write more unit tests.

composition-and-forwarding approach for a class with two Lists

I have read Item 16 from Effective Java and
Prefer composition over inheritance? and now try to apply it to the code written 1 year ago, when I have started getting to know Java.
I am trying to model an animal, which can have traits, i.e. Swimming, Carnivorous, etc. and get different type of food.
public class Animal {
private final List<Trait> traits = new ArrayList<Trait>();
private final List<Food> eatenFood = new ArrayList<Food>();
}
In Item 16 composition-and-forwarding reuseable approach is suggested:
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {this.s = s;}
//implement all interface methods
public void clear() {s.clear();}
//and so on
}
public class InstrumentedSet<E> extends ForwardingSet<E> {
//counter for how many elements have been added since set was created
}
I can implement ForwardingList<E> but I am not sure on how I would apply it twice for Animal class. Now in Animal I have many methods like below for traits and also for eatenFood. This seems akward to me.
public boolean addTrait (Trait trait) {
return traits.add(trait);
}
public boolean removeTrait (Trait trait) {
return traits.remove(trait);
}
How would you redesign the Animal class?
Should I keep it as it is or try to apply ForwardingList?
There is no reason you'd want to specialize a List for this problem. You are already using Composition here, and it's pretty much what I would expect from the class.
Composition is basically creating a class which has one (or usually more) members. Forwarding is effectively having your methods simply make a call to one of the objects it holds, to handle it. This is exactly what you're already doing.
Anyhow, the methods you mention are exactly the sort of methods I would expect for a class that has-a Trait. I would expect similar addFood / removeFood sorts of methods for the food. If they're wrong, they're the exact sort of wrong that pretty much everyone does.
IIRC (my copy of Effective Java is at work): ForwardingSet's existence was simply because you cannot safely extend a class that wasn't explicitly designed to be extended. If self-usage patterns etc. aren't documented, you can't reasonably delegate calls to super methods because you don't know that addAll may or may not call add repeatedly for the default implemntation. You can, however, safely delegate calls because the object you are delegating to will never make a call the wrapper object. This absolutely doesn't apply here; you're already delegating calls to the list.

Categories