Builder pattern vs. config object - java

The builder pattern is popular to create immutable objects, but there is some programming overhead to create a builder. So I wonder why not simply using a config object.
The usage of a builder would look like this:
Product p = Product.Builder.name("Vodka").alcohol(0.38).size(0.7).price(17.99).build();
It is obvious that this is very readable and concise, but you have to implement the builder:
public class Product {
public final String name;
public final float alcohol;
public final float size;
public final float price;
private Product(Builder builder) {
this.name = builder.name;
this.alcohol = builder.alcohol;
this.size = builder.size;
this.price = builder.price;
}
public static class Builder {
private String name;
private float alcohol;
private float size;
private float price;
// mandatory
public static Builder name(String name) {
Builder b = new Builder();
b.name = name;
return b;
}
public Builder alcohol(float alcohol) {
this.alcohol = alcohol;
return.this;
}
public Builder size(float size) {
this.size = size;
return.this;
}
public Builder price(float price) {
this.price = price;
return.this;
}
public Product build() {
return new Product(this);
}
}
}
My idea is, to reduce the code by using a simple config object like this:
class ProductConfig {
public String name;
public float alcohol;
public float size;
public float price;
// name is still mandatory
public ProductConfig(String name) {
this.name = name;
}
}
public class Product {
public final String name;
public final float alcohol;
public final float size;
public final float price;
public Product(ProductConfig config) {
this.name = config.name;
this.alcohol = config.alcohol;
this.size = config.size;
this.price = config.price;
}
}
Usage:
ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);
This usage needs a few more lines but is also very readable, but the implementation is much simpler and maybe it is easier to understand for someone who isn't familiar with the builder pattern. By the way: is there a name for this pattern?
Is there a drawback in the config approach that I've overlooked?

The builder pattern improves decoupling - your Product can be an interface and the only class that knows about the implementation (or implementations, in some cases) is the builder. If the builder also implements an interface then you can inject this into your code to increase decoupling further.
This decoupling means your code is more maintainable and easier to test.

You are losing several advantages of the builder pattern, as has already been pointed out (new is ugly and harder to maintain and leaking details compared to a clean builder).
The one I miss the most however is that the builder pattern can be used to provide what are called "fluent interfaces".
Instead of this:
ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);
You can do:
ProductFactory.create()
.drink("Vodka")
.whereAlcohoolLevelIs(0.38)
.inABottleSized(0.7)
.pricedAt(17.99)
.build();
Not everyone like fluent interfaces, but they are definitely a very nice use of the builder pattern (all fluent interfaces should use the builder pattern, but not all builder pattern are fluent interfaces).
Some great Java collections, like the Google collections, makes both very liberal and very good use of "fluent interfaces". I'd pick these any day over your "easier-to-type/less characters" approach : )

The configuration pattern and the builder pattern are functionally equivalent. They both solve the same problems -
Eliminate the need for multiple constructor signatures
Allow fields to only be set during construction
Allow consumers to only set values they care about and have logical defaults for the other values
Anything you want to do in one of these patterns you can do in the other, such as only allowing state to be set with methods that do validation and setting state with encapsulated logic. The only real difference is if you like creating objects with the new key term or if you like calling a .build() method.

What problem do you try to solve with your pattern? The builder pattern is used for objects with many (optional) parameters in order to prevent tons of different constructors or very long ones. It also keeps your object in a consistent state (vs. javabean pattern) during construction.
The difference between builder and "config object" (feels like a good name) is, that you still have to create the object with the same params by constructor or getter/setter. This a) doesnt solve the constructor problem or b) keeps the config object in inconsistent state. Inconsistent states of the config object dont really hurt it but you could pass an unfinished config object as a param. [Michids link to phantom types seem to solve this problem, but that again kills readability (new Foo<TRUE,TRUE, TRUE, FALSE, TRUE> kinda sucks).] Thats the big advantage of the builder pattern: you can validate your params before you create an object and you can return any subtype (acts like a factory).
Config objects are valid for sets of params which are all mandatory. Ive seen this pattern many times in .NET or java before.

Have you considered using builder-builder?
I do think the builder (with prefixes like "With") reads more natrually/fluently.

I personally feel that the builder pattern at first sight offers you cleaner code where these objects are in fact used. On the other hand, not having getters/setters will not be very usable by a lot of frameworks that expect camel case getters/setters. This is a serious draw back I feel.
What I also like with getters/setters is that you clearly see what you are doing: get or set. I feel with the builder I am losing a bit of intuitive clarity here.
I know that many people have read a specific book and that now all of a sudden, the builder pattern has enjoyed the hype, as if it were the new iPhone. However, I am not an early adopter. I only use "the new way" when it really really proves a big time saver on whatever territory, being it performance, maintenance, coding...
My hands-on experience is that I usually am better of with getters/setters and constructors. It allows me to reuse these POJO's for any purpose.
Although I see the purpose of your Config Object, I also think it is even more overhead than the builder, and for what? What is wrong with setters?
Maybe we need to invent a WITH clause:
example, let's say you have
public Class FooBar() {
private String foo;
public void setFoo(String bar) {
this.foo = bar;
}
public String getFoo() {
return this.foo;
}
}
public static void main(String []args) {
FooBar fuBar = new FooBar();
String myBar;
with fuBar {
setFoo("bar");
myBar = getFoo();
}
}
Ah I dunno... I think this may yet result in quicker code writing without all the inner class hassle. Does any one have connections with the Oracle Java guru's?
It doesn't look as clean as using an object with a builder, but you save builder-construction time. And you can still use the class as a regular pojo/bean which can be used in frameworks...
Would you guys actually like this clause or you think it would rather suck?
Cheers

IMO, the builder pattern is much more roboust if you have things like validation, etc.
The builder pattern in your case can be changed to do the following:
Product p = new ProductBuilder("pName").alcohol(0.38).size(0.7).price(17.99).build();
The build() method can do all the validation stuff that is needed for your builder.
The builder pattern also has several design advangates (all of which may not be applicable in your case). For deatils check this question

The main drawback is that it is not in Joshua's book, so drones can't wrap their heads around it.
You are using a simple value object to hold multiple arguments a function(/method/constructor) needs, there is nothing wrong with that, it has been done for ages. As long as we don't have named optional parameters we'll have to devise workarounds like this - it's a shame, not some god damn brilliant inventions from the gods in the Sun.
The real difference is that you expose fields directly. Joshua would never have a public mutable field - but he writes APIs that will be used by millions of people most of which are morons, and the APIs must be safe to evolve for decades to come, and they can allocate many man months just to design a simple class
Who are we to emmulate that?

You should not use the public field, but protected or private. For accesing then you should use the getters and setter to keep the encapsulation..

Related

Is there any better way to make a constructor that fills in for all the possible variables rather than writing them all out?

Is there any less time consuming method of creating a program that can take all of my given parameters and regardless of what they are simply fill in for those values? For example given optional 4 parameters that I want to fill will I have to write a constructor for each possible combination?
I'm new to Java but I've already written one class where I did this, and it took me quite some time and was a somewhat monotonous, I was just wondering if there was a faster method of doing it.
Constructors are not the only way to construct objects. There are a few (creational) design patterns that accomplish the same goal that you should consider. In fact, it could be argued that constructors should be considered your last resort to build objects. I strongly recommend you do some research into Creational Design Patterns
For this problem, I think you can take advantage of The Builder Pattern.
Builder Pattern Explained
The builder pattern allows clients to build an object in stages. This is possible because instantiation of the required object is deferred to the builder until all needed attributes are obtained.
Consider the process of building a "widget". Assume this "widget" has two components, of which only one is required. You can either A) build the "widget" without the optional component, or B) you can assemble the "widget" with the required part, pause the build process and resume at a later time when the optional component is available. When using a conventional constructor, this is not possible.
Another advantage of the Builder pattern is that you don't need to create a constructor with a lot of parameters that are not required. And it eliminates the need to have multiple permutations of the constructor with different parameters. In fact, sometimes this is not even possible. For example, if the class in question has eight String parameters, you cannot have two constructors with four Strings each.
When implementing this pattern, the "widget" being built has only one constructor, and it is private. The constructor of the class is only accessible to the builder.
Lastly, unlike conventional "setter" methods, the "setter" methods of a builder return an instance of the builder itself. This allows chaining method calls to set multiple (optional) parameters. For example; builder.setOptionalParm1(val1).setOptionalParm2(val2)... etc.
Builder Pattern Code Example
public class ImmutableWidget {
private final String required;
private final String optional;
private ImmutableWidget (Builder builder) {
this.required = builder.required;
this.optional = builder.optional;
}
#Override
public String toString () {
return "Required: " + required + "; Optional: " + optional;
}
public String getRequired () {
return required;
}
public String getOptional () {
return optional;
}
public static class Builder {
private final String required;
private String optional;
public Builder (String required) {
this.required = required;
}
public Builder setOptional (String optional) {
this.optional = optional;
return this;
}
public ImmutableWidget build () {
return new ImmutableWidget (this);
}
}
public static void main (String... strings) {
Builder builder = new ImmutableWidget.Builder ("required");
builder.setOptional("optional"); // This step is not required
ImmutableWidget widget = builder.build();
System.out.println(widget);
}
}
Additional information
Basic Builder Pattern topic: Immutable Widget YouTube video
Advanced Builder Pattern topic: Using Builder Pattern with Class
Hierarchies
This post by Vitalii Fedorenko explains what to do: https://stackoverflow.com/a/12994104/20421925
Vitallii's post is a lot to take in (I'm still trying to understand it myself). Let me know if you need any assistance understanding it.

Clearing doubts about the builder pattern

I am learning about the builder pattern, and so far I understood that, it is a great alternative to the commonly patterns used for initialization:
Telescoping Constructor Pattern
JavaBean Pattern
The thing is, I don't really like to remove the getters and setters from the objects in my domain model. I always like to keep them as POJOs. One of the reasons I don't like it is:
If i don't use POJOs, then it is not easy to annotate the variables when using ORM frameworks...
So here are my doubts:
-Is it possible to implement the builder pattern without using static inner classes?
-If I have to use the builder pattern by using the inner class, do you think it is correct to keep the getters and the setters?
-I did a little example for practice where I tried to avoid the inner class.
Could you let me what do you think about it?
Product
public class Product
{
private String color;
private int price;
public Product() {
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String toString() {
return getColor() + "\n" + getPrice();
}
}
Builder
public class Builder
{
private Product product;
public Builder() {
product = new Product();
}
public Builder withColor(String color) {
product.setColor(color);
return this;
}
public Builder withPrice(int price) {
product.setPrice(price);
return this;
}
public Product build() {
return product;
}
}**
Client
public class Client
{
public static void main(String[] args) {
System.out.println(new Builder().withColor("Black").withPrice(11).build());
System.out.println("-----------------------------------------------------");
System.out.println(new Builder().withColor("Blue").withPrice(12).build());
}
}
The Builder pattern is useful to create immutable objects and avoid several constructors with optional parameters.
IMO using Builder pattern to build a POJO which can be updated using setters is useless. You only create an additional class.
Depending on the ORM framework used, it might not need the presence of setter method. But only assigning members values through reflection.
Product class:
public final class Product {
private final String color;
private final int price;
public Product(Builder builder) {
this.color = builder.getColor();
this.price = builder.getPrice();
}
public String getColor() {
return color;
}
public int getPrice() {
return price;
}
public String toString() {
return getColor() + "\n" + getPrice();
}
}
Builder class:
public final class Builder {
private String color;
private int price;
public Builder() {
// Assign any default values
}
public Builder color(String color) {
this.color = color;
return this;
}
public Builder price(int price) {
this.price = price;
return this;
}
protected String getColor() {
return color;
}
protected int getPrice() {
return price;
}
public Product build() {
return new Product(this);
}
}
The builder pattern is most useful in the context of immutable objects. Immutable objects don't have setters by definition. So all of their properties have to be squeezed into the constructor. This is where the builder pattern comes in handy. It allows you to split the initialization of a complex immutable object into multiple, self-explaining instructions so you don't need to have constructor calls like this fictional example all over you code where you can't tell which argument does what:
Thing foo = new Thing(1, 125, Thing.SOMETHING, new Whatchamacallit(17, 676), getStuffManager(StuffManager.ZOMG), true, false, false, maybe);
I don't find that the Builder pattern creates any signficant value when the created object is mutable. Everything you do through the builder can also be done with the created object directly.
Also, I think that your program above is not a textbook example of the builder pattern. You usually don't create an object by passing the builder to the constructor. You create an object by calling a create method on the builder which then passes all its properties to the constructor of the object. This pattern has the advantage that it gives the builder the opportunity to check its internal state for consistency and maybe throw an exception before starting to build the object.
The java StringBuilder class is a good example (the create method being tostring in this case).
What does using a builder here actually gain you?
Nothing as far as I can see: you could just create a new Product and use the getters and setters on it directly. If you have a simple POJO then there is absolutely nothing wrong with:
Product p=new Product();
p.setColour("Black");
p.setPrice(11);
doSomethingWith(p);
Saving a few characters of typing is IMHO not worth introducing a new class / builder abstraction.
Builders are more useful in situations like the following:
You want to create an immutable object (and hence can't use setters)
If you have complicated factory logic that cannot easily be expressed with simple getters and setters or that you want to re-use in different ways
(Occasionally) when you want to have different parts of the code base configure different aspects of the builder for some reason.
The builder pattern lends itself well to producing immutable classes, but it can still be a good option for mutable classes too.
A builder is a reasonable design choice in any situation where an object contains many fields that need to be set during construction; particularly if sensible defaults can be chosen for several of the values.
Whether you use an inner class depends upon your goals. If you wish to force construction through the builder, you can define the builder as an inner class and ensure the outer class only has a private constructor.
Here are Builder collaborations from GoF book:
Collaborations
1. The client creates the Director object and configures it with the desired Builder object.
2. Director notifies the builder whenever a part of the product should be built.
3. Builder handles requests from the director and adds parts to the product.
3. The client retrieves the product from the builder.
The Builder pattern focuses on constructing a complex object step by step. Builder returns the product as a final step. The returned class in absence of the setters may be as good as immutable. With setters, it can be modified. And inner classes help mask the details.
Another point worth noting is that a major motivation behind creational design patterns is that the client doesn't worry about creating the product. The object creation process is delegated to factory, builder, etc. The client doesn't have to worry about object creation. It will specify what it wants and will get it as a result of delegated creation process.
Is it possible to implement the builder pattern without using static
inner classes?
Absolutely, yes. As far as the Builder design pattern is concerned, it does not make any difference if the Builder is an inner class or not.
-If I have to use the builder pattern by using the inner class, do you think it is correct to keep the getters and the setters?
Yes, it is ok. it is kind of like, build the object using a certain template and then customize it, if needed.
-I did a little example for practice where I tried to avoid the inner
class. Could you let me what do you think about it?
Two problems -
the example does not justify the usage of Builder pattern. Builder pattern is used to build a complex object. So if you can simply build product as :
Product p = new Product();
p.setColor(c);
p.setPrice(prc);
Then there is hardly any benefit in the way you have shown.
Product should not have a dependency on Builder.
I found myself thinking if getters are any good in a builder. A builder shouldn't generally be used as a return value - a single method or class should be responsible for creation of the entity using builder. Thus, the method (or class) should keep the information it needs instead of getting it back.
For those reasons, I decided not to use any getters in the builder class. Builder only has setters (be it withAbc(...), setAbc(...) or abc(...)), build() and possibly some private methods like validate().
Using class Product, a sample entity looks like this:
class Product {
private final String color;
private final int price;
private Product(ProductBuilder builder) {
this.color = builder.color;
this.price = builder.price;
}
// equals, hashCode, toString
public builder() {
return new ProductBuilder(this);
}
public static emptyBuilder() {
return new ProductBuilder();
}
public String getColor() {
return color;
}
public int getPrice() {
return price;
}
Now, a builder class is an inner class of the entity, which allows me to use private constructors.
public static class ProductBuilder {
private String color;
private int price;
private ProductBuilder() {
}
private ProductBuilder(Product entity) {
this.color = entity.color;
this.price = entity.price;
}
public ProductBuilder withColor(String color) {
this.color = color;
return this;
}
public ProductBuilder withPrice(int price) {
this.price = price;
return this;
}
public Product build() {
return new Product(this.validate());
}
private ProductBuilder validate() {
if (color == null) {
throw new IllegalStateException("color is null");
}
return this;
}
}
As you can see, I added method builder() to get builder as a copy of the instance and emptyBuilder() as a factory method to hide constructor (maybe there is a better name for it).
Also, when constructing an immutable class, make sure everything inside is immutable as well. Collections are tricky, you have to make a copy, then use Collections.unmodifiable*(...) on it to ensure nobody has a reference to the collection lying under the unmodifiable wrapper.
EDIT: Allegedly, you need getters if you have abstract superclass. That is an overstatement. You only need it if you have a constructor with all params. If you pass the builder instead, like me, you get:
class Product extends Something { ...
private Product(ProductBuilder builder) {
super(builder); // that one must be protected, not private
...
}
public static class ProductBuilder extends SomethingBuilder { ...
protected ProductBuilder validate() {
super.validate();
...
}
}
}
So, do we need getters? This time, not really. We're still fine without them. Some other ideas?
Builder is about several things and you may want to utilize only one aspect: fluent API. You may attain the best fit for your needs by just changing your setters to return this instead of void. Then you can use the chained-setter idiom: return new MyBean().setCheese(cheese).setBacon(bacon);
On a side note, the term "POJO" does not mean the same as "JavaBean". In fact, sometimes these two terms are used as opposites. The point of a POJO is that it doesn't conform to anything else than being a Java object. It may use public variables, for example.

how to reduce the code of constructor overloading

In my one class I have many constructors like this..
public MyData(int position,String songName,String duration, boolean e) {
//initialization of above variable like int, string,string and boolean
}
public MyData(String songName, String artistName, String duration,String downloadPath, String songSize, String albumName,String url,String trackId, boolean e)
{
//initialization of above variable like String,String,String,String,String,String,String,String and boolean
}
and some more like above.
Now the calling time, I'm calling that constructor only that I require data. but I don't think my flow is good so I need some help to reduce my code as well as creation of good flow.
If anybody have a good flow to achieve this, then please share.
Thanks in advance.
Assuming you're effectively applying defaults, usually the best approach is to have one "full" constructor and make the others call it. For example:
public Foo(String name)
{
// Default the description to null
this(name, null);
}
public Foo(String name, String description)
{
this.name = name;
this.description = description;
}
You still end up with quite a lot of cruft in terms of overloaded constructors, but at least each of those "extra" constructors contains no actual code - just a call to another constructor. If possible, chain the constructors together so that the default for any particular value is only specified in one place - or use a constant. That way you get consistency.
Another option is to use a "parameter object" following the builder pattern - create another class whose sole purpose is to hold the data for the constructor parameters. This should be mutable, with setters for all of the different values. Often it's useful to make the setters return the builder, so you can use:
FooParameters parameters = new FooParameters()
.setName("some name")
.setDescription("some description");
// Either a constructor call at the end, or give FooParameters
// a build() or create() method
Foo foo = new Foo(parameters);
This is particularly useful if the main type you're constructing is an immutable type - it means you can apply conditional logic in the calling code to set some parameters but not others. The Java framework itself uses this approach in ProcessBuilder, although personally I'm not keen on the way it overloads method names to either return a value or set a value based on whether you provide an argument :(
Note the comment above the constructor call in the final snippet - if your helper class is only ever helpful for creating objects of a single type, you can give it an extra method (build, create, start, whatever is most appropriate) to take the place of the constructor call. This allows you to build the whole final object in a fluent way.
One option in the Java implementation of the builder pattern is to use a nested type, e.g.
Foo foo = new Foo.Builder().setName(...).setDescription(...).build();
That avoids polluting your package with another class which is only useful for building instances of Foo.
You may want to have another object that is responsible for creating the object through the builder pattern. For example, you could define an object like this:
public class SongBuilder {
private String artistName;
private String songTitle;
/* ... everything else ... */
public SongBuilder setArtistName(String name) {
this.artistName = name;
return this;
}
public SongBuilder setSongTitle(String title) {
this.songTitle = title;
return this;
}
/* ... everything else ... */
public Song create() {
return new Song(artistName, songTitle, /* ... everything else ... */);
}
}
You could then define a single constructor for Song that takes in all the data. To make a Song, you could then write
Song s = new SongBuilder().setSongTitle("Still Alive").setArtistName("GLaDOS").create();
The advantage of this approach is that you can set a reasonable default for all the parameters, then just call the appropriate set functions for parameters that you actually use. It also allows you to add new parameters easily without having to go back and rewrite important code.
Alternatively, as Jon Skeet points out, you can have multiple constructors that all call one another. The advantage of the builder pattern over this approach is that if you have n different parameters, there are 2n combinations of constructors you'd need to write, whereas you only need one builder.
Hope this helps!

In which scenarios do you use encapsulation?

I would like to know in what scenarios you use encapsulation. The purpose of this question is collaborative. So feel free to share your own experience when the subject is encapsulation.
Some scenarios:
Calculated property
public class Order {
private List<ListItem> listItems = new ArrayList<ListItem>();
public double getTotal() {
double total = 0;
for(ListItem listItem: listItems)
total += listItem.getQuantity() * listItem.getPropduct().getPrice();
return total;
}
}
Self-validating domain objects
public class Person {
private String name;
public void setName(String name) {
if(StringUtils.isBlank(name)) {
throw new NotEmptyException("name", name);
}
this.name = name;
}
}
Makes use of other kind of classes for some special behavior
public class Person {
private MutableInt id = new MutableInt();
/**
* Integer itself is immutable
*/
public Integer getId() {
retur id.intValue();
}
}
Conversion
public class Person {
public String enabled;
public boolean isEnabled() {
return "Y".equals(enabled);
}
}
Simply, I prefer to use strong encapsulation in all non-private APIs that I design/implement.
The only case where habitually don't use strong encapsulation is with private nested classes that are (and need to be) little more than ersatz struct declarations. My reasoning is that the private class is sufficiently encapsulated by being nested and private.
I am also prepared to relax encapsulation (a bit) if there are compelling performance reasons for doing this. This relaxation usually consists of leaking internal arrays / collections when the cost of copying them is prohibitive. And it always makes me feel uncomfortable doing this ...
I encapsulate when there is a scenario in which the user can screw it up. e.g., if I was writing a class that displayed text, I would not encapsulate the fact that I hold a string, because any string is valid for display.
Encapsulation exists for validation and interface change. If you have a parameter that needs no validation (and the interface is well-defined), there's no point in encapsulating it, especially if you use a language which doesn't come with any in-built tools for it, like Java (tools being, for example, C# properties).
Encapsulation is a tool like any other and should not be thrown all over everywhere just because you can.

What would be the best way to implement a constant object?

First of all I should probably say that the term 'constant object' is probably not quite right and might already mean something completely different from what I am thinking of, but it is the best term I can think of to describe what I am talking about.
So basically I am designing an application and I have come across something that seems like there is probably an existing design pattern for but I don't know what it is or what to search for, so I am going to describe what it is I am trying to do and I am looking for suggestions as to the best way to implement it.
Lets say you have a class:
public class MyClass {
private String name;
private String description;
private int value;
public MyClass(String name, String description, int value) {
this.name = name;
this.description = description;
this.value = value;
}
// And I guess some getters and setters here.
}
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
At first I thought that I should declare some static constants somewhere, e.g.
public static final String INSTANCE_1_DATA_FILE = "path/to/instance1/file";
public static final String INSTANCE_2_DATA_FILE = "path/to/instance2/file";
public static final String INSTANCE_3_DATA_FILE = "path/to/instance3/file";
public static final MyClass INSTANCE_1 = new MyClass(getNameFromFile(INSTANCE_1_DATA_FILE), getDescriptionFromFile(INSTANCE_1_DATA_FILE), getValueFromFile(INSTANCE_1_DATA_FILE));
public static final MyClass INSTANCE_2 = new MyClass(getNameFromFile(INSTANCE_2_DATA_FILE), getDescriptionFromFile(INSTANCE_2_DATA_FILE), getValueFromFile(INSTANCE_2_DATA_FILE));
public static final MyClass INSTANCE_3 = new MyClass(getNameFromFile(INSTANCE_3_DATA_FILE), getDescriptionFromFile(INSTANCE_3_DATA_FILE), getValueFromFile(INSTANCE_3_DATA_FILE));
Obvisouly now, whenever I want to use one of the 3 instances I can just refer directly to the constants.
But I started thinking that there might be a cleaner way to handle this and the next thing I thought about was doing something like:
public MyClassInstance1 extends MyClass {
private static final String FILE_NAME = "path/to/instance1/file";
public String getName() {
if (name == null) {
name = getNameFromFile(FILE_NAME);
}
return name;
}
// etc.
}
Now whenever I want to use the instances of MyClass I can just use the one I want e.g.
private MyClass myInstance = new MyClassInstance2();
Or probably even better would be to make them singletons and just do:
private MyClass myInstance = MyClassInstance3.getInstance();
But I can't help but think that this is also not the right way to handle this situation. Am I overthinking the problem? Should I just have a switch statement somewhere e.g.
public class MyClass {
public enum Instance { ONE, TWO, THREE }
public static String getName(Instance instance) {
switch(instance) {
case ONE:
return getNameFromFile(INSTANCE_1_DATA_FILE);
break;
case TWO:
etc.
}
}
}
Can anyone tell me the best way to implement this? Note that I have written the sample code in Java because that is my strongest language, but I will probably be implementing the application in C++, so at the moment I am more looking for language independent design patterns (or just for someone to tell me to go with one of the simple solutions I have already mentioned).
If you want the values to be constant, then you will not need setters, otherwise code can simply change the values in your constants, making them not very constant. In C++, you can just declare the instances const, although I'd still get rid of the setters, since someone could always cast away the const.
The pattern looks ok, although the fact that you are creating a new instance each time one is requested, is not usual for constants.
In java, you can create enums that are "smart" e.g.
public enum MyClass {
ONE(INSTANCE_1_DATA_FILE),
TWO(INSTANCE_2_DATA_FILE),
//etc...
private MyClass(String dataFile)
{
this(getNameFromDataFile(dataFile), other values...)
}
private MyClass(String name, String data, etc...)
{
this.name = name;
// etc..
}
public String getName()
{
return name;
}
}
In C++, you would create your MyClass, with a private constructor that takes the filename and whatever else it needs to initialize, and create static const members in MyClass for each instance, with the values assigned a new instance of MyClass created using the private constructor.
EDIT: But now I see the scenario I don't think this is a good idea having static values. If the types of ActivityLevel are fundamental to your application, then you can enumerate the different type of activity level as constants, e.g. a java or string enum, but they are just placeholders. The actual ActivityDescription instances should come from a data access layer or provider of some kind.
e.g.
enum ActivityLevel { LOW, MED, HIGH }
class ActivityDescription
{
String name;
String otherDetails;
String description; // etc..
// perhaps also
// ActivityLevel activityLevel;
// constructor and getters
// this is an immutable value object
}
interface ActivityDescriptionProvider
{
ActivityDescription getDescription(ActivityLevel activityLevel);
}
You can implement the provider using statics if you want, or an enum of ActivityDescription instnaces, or better still a Map of ActivityLevel to ActivityDescription that you load from a file, fetch from spring config etc. The main point is that using an interface to fetch the actual description for a given ActivityLevel decouples your application code from the mechanics of how those descriptions are produced in the system. It also makes it possible to mock the implementation of the interface when testing the UI. You can stress the UI with a mock implementation in ways that is not possible with a fixed static data set.
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
I'd use an enum. And then rather in this flavor:
public enum MyEnum {
ONE("path/to/instance1/file"),
TWO("path/to/instance2/file"),
THREE("path/to/instance3/file");
private String name;
private MyEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Which can be used as follows:
MyEnum one = MyEnum.ONE;
String name = one.getName();
(I'm too slow once again, you already accepted an answer, but here it is anyway...)
You want to (a) prevent changes to the data held in objects of MyClass, and (b) allow only a fixed set of MyClass objects to exist, implying that runtime code should not be able to create new instances of MyClass.
Your initial example has a public constructor, which violates (b)
I'd use a Factory approach so the Factory is the only thing that can create instances, and the class doesn't provide any setters so it's immutable.
Depending on how much flexibility you want for the future, you could put the factory and the class in the same package and limit scope that way, or you could make MyClass an inner class within the factory. You may also consider making MyClass an interface separate from its implementation.
A properties file could be used to configure the factory itself.
The properties file (e.g. "foo.properties") could look something like
one=/path/to/datafile1
two=/another/path/to/datafile2
three=/path/to/datafile3
I use "Foo" instead of "MyClass" in the (Java) examples below.
public class FooFactory
{
/** A place to hold the only existing instances of the class */
private final Map<String, Foo> instances = new HashMap<String, Foo>();
/** Creates a factory to manufacture Foo objects */
// I'm using 'configFile' as the name of a properties file,
// but this could use a Properties object, or a File object.
public FooFactory(String configfile)
{
Properties p = new Properties();
InputStream in = this.getClass().getResourceAsStream();
p.load(in); // ignoring the fact that IOExceptions can be thrown
// Create all the objects as specified in the factory properties
for (String key : p.keys())
{
String datafile = p.getProperty(key);
Foo obj = new Foo(datafile);
instances.put(key, obj);
}
}
public Foo getFoo(String which)
{
return instances.get(which);
}
/** The objects handed out by the factory - your "MyClass" */
public class Foo
{
private String name;
private String description;
private int value;
private Foo(String datafile)
{
// read the datafile to set name, description, and value
}
}
}
You're set to allow only your predefined instances, which can't be changed at runtime, but you can set it all up differently for another run at a later time.
Your first method seems to me like the best and the least prone to code rot. I'm not impressed by the idea of subclassing an object just to change the file name that contains the data that will be used to build it.
Of course, you could maybe improve on your original idea by wrapping these all in an outer class that provides some sort of enumeration access. A collection of MyClass's in other words. But I think you should discard this subclassing idea.
First, you really should be limiting where you use these instances in the code. Use them in as few places as possible. Given these are file names, I expect you want three class instances which accesses the files. How many classes are required depends on what your want to do with them? Look at the Singleton pattern for these classes.
Now you don't need the constants, but could have a helper class which will read the file containing the file names and supply them to the reader class. The code to find then name could also be a method called by the static initializer of the Singleton.
The common approach is to use a map:
private static final Map<String, YouClass> mapIt =
new HashMap<String, YouClass>(){{
put("one", new YourClass("/name", "desc", 1 )),
put("two", new YourClass("/name/two", "desc2", 2 )),
put("three", new YourClass("/name/three", "desc", 3 ))
}}
public static YourClass getInstance( String named ) {
return mapIt.get( named );
}
Next time you need it:
YouClass toUse = YourClass.getInstance("one");
Probably using strings as keys is not the best option but you get the idea.

Categories