Repetition in Builder Pattern - java

I'm using a builder pattern (as explained in Joshua Bloch's Effective Java) for a few things, and there's a particularly annoying repetition involved:
public class Foo {
private String name;
private int age;
public static class Builder implements IBuilder {
private String name;
private int age;
Builder name(String value) {
name = value;
return this;
}
Builder age(int value) {
age = value;
return this;
}
Foo build() {
return new Foo(this);
}
}
private Foo(Builder builder) {
name = builder.name;
age = builder.age;
}
}
It's small, but annoying. I have to declare the variable in each class. I tried creating a class with the fields and extending that class, but I got the error: {variable_name} has private access in {class_name}.
Is there a way to do this, without making the variables public?

If your builders are purely for capturing a bunch of state (and not doing any intermediate computation), you can solve the repetition by just defining the builder interface, then writing a Java proxy generator.
If you were to do this, you couldn't rely on the outer class having access to the builder (inner) class's private fields. To work around that, you would need to define accessors for each field, too. So for example:
public class Foo {
public interface Builder extends IBuilder {
Builder name(String name);
String name();
Builder age(int age);
int age();
...
}
public static Builder builder() {
return BuilderFramework.newInstance(Builder.class);
}
public Foo(Builder builder) {
...
}
}
Alternatively, your builder could expose all the fields in a Map or similar structure. Using that route, your interface would only need the chaining setters. But you give up compile time checking of all your field usages within the constructor. IMHO, too big a compromise.

Related

Is it correct to have static factory method to get a new instance with one field updated?

I think the title is self-descriptive but I will give an example to elaborate on my question. I have a DTO class with few fields (a CarDataTransferObj class in my example). In another class (let's call it class A) I need to create a new instance of that object few times, but with only one field updated (length field in my example). Given DTO must be immutable in class A. As there is "many" fields in the class CarDataTransferObj, I thought about following approach (to avoid repeating code in class A):
#Builder
public class CarDataTransferObj {
private Integer id;
private String color;
private String manufacturer;
private String model;
private String uniqueIdNr;
private Integer nrOfDoors;
private EngineType engineType;
private Integer length;
private Integer safetyLevel;
public static CarDataTransferObj newInstanceWithUpdatedLength(final CarDataTransferObj car, final Integer newLength) {
return CarDataTransferObj.builder()
.id(car.getId())
.color(car.getColor())
.manufacturer(car.getManufacturer())
.model(car.getModel())
.uniqueIdNr(car.getUniqueIdNr())
.nrOfDoors(car.getNrOfDoors())
.engineType(car.getEngineType())
.length(newLength)
.safetyLevel(car.getSafetyLevel())
.build();
}
}
For me it smells like a little anti-pattern usage of static factory methods. I am not sure whether it's acceptable or not, hence the question.
Is using static factory method in the presented way an anti-pattern, and should be avoided ?
In my searching, I didn't come across anyone calling this1 an anti-pattern.
However, it is clear that if you try to do this using a classic builder that is not specifically implemented to support this mode of operation .... it won't work. For instance, the example CarBuilderImpl in the Wikipedia article on the Builder design pattern puts the state into an eagerly created Car instance. The build() method simply returns that object. If you tried to reuse that builder in the way that you propose, you would end up modifying a Car that has already been built.
There is another problem you would need to worry about. In we modified the Wikipedia CarBuilder example to add actual wheels (rather than a number of wheels) to the Car being built, we have to worry about creating cars that share the same wheels.
You could address these things in a builder implementation, but it is unclear whether the benefits out-weigh the costs.
If you then transfer this thinking to doing this using a factory method, you come to a slightly different conclusion.
If you are doing this as a "one-off", that's probably OK. You have a specific need, the code is clunky ... but so is the problem.
If you needed to do this for lots of different parameters, or combinations of parameters, this is not going to scale.
If the objects that are created are mutable, then this approach is could be problematic in a multi-threaded environment depending on how you control access to the objects you are using as templates.
1 - There are no clear measurable criteria for whether something is an anti-pattern or not. It is a matter of opinion. Admittedly, for many anti-patterns, there will be wide-scale agreement on that opinion.
It seems a little inefficient to construct an entirely new instance via a builder every time you want to make a new copy with a small modification. More significantly, it sounds like the places where you need the class to be immutable are isolated to places like class A. Why not try something like this:
public interface ICarDataTransferObject {
public Integer GetId();
public String GetColor();
public String GetManufacturer();
public String GetModel();
public String GetUUID();
public Integer GetDoorCount();
public EngineType GetEngineType();
public Integer GetLength();
public Integer GetSafteyLevel();
}
public class CarDataTransferObject Implements ICarDataTransferObject {
private Integer _id;
private String _color;
private String _manufacturer;
private String _model;
private String _uniqueIdNr;
private Integer _nrOfDoors;
private EngineType _engineType;
private Integer _length;
private Integer _safetyLevel;
public Integer GetId() { return _id; }
public void SetId(Integer id) { _id = id; }
public String GetColor() { return _color; }
public void SetColor(String color) { _color = color; }
public String GetManufacturer() { return _manufacturer; }
public void SetManufacturer(String manufacturer) { _manufacturer = manufacturer; }
public String GetModel() { return _model; }
public void SetModel(String model) { _model = model; }
public String GetUUID() { return _uniqueIdNr; }
public void SetUUID(String uuid) { _uniqueIdNr = uuid; }
public Integer GetDoorCount() { return _nrOfDoors; }
public void SetDoorCount(Integer count) { _nrOfDoors = count; }
public EngineType GetEngineType() { return _engineType; }
public void SetEngineType(EngineType et) { _engineType = et; }
public Integer GetLength() { return _length; }
public void SetLength(Integer length) { _length = length; }
public Integer GetSafteyLevel() { return _safetyLevel; }
public void SetSafteyLevel(Integer level) { _safteyLevel = level; }
public CarDataTransferObject() {}
public CarDataTransferObject(ICarDataTransferObject other) { ... }
public ReadOnlyCarDataTransferObject AsReadOnly() {
return ReadOnlyCarDataTransferObject (this);
}
}
}
public class ReadOnlyCarDataTransferObject Implements ICarDataTransferObject {
private ICarDataTransferObject _dto = null;
public Integer GetId() { return _dto.GetId(); }
public String GetColor() { return _dto.GetColor(); }
public String GetManufacturer() { return _dto.GetManufacturer(); }
public String GetModel() { return _dto.GetModel(); }
public String GetUUID() { return _dto.GetUUID(); }
public Integer GetDoorCount() { return _dto.GetDoorCount(); }
public EngineType GetEngineType() { return _dto.GetEngineType(); }
public Integer GetLength() { return _dto.GetLength(); }
public Integer GetSafteyLevel() { return _dto.GetSafteyLevel; }
public ReadOnlyCarDataTransferObject (ICarDataTransferObject other) {
_dto = other;
}
}
Now when you want class A to have a copy no one can modify, just use the copy constructor and only expose a ReadOnly version of that copy.
public class A {
ICarDataTransferObject _dto;
ReadOnlyCarDataTransferObject _readOnlyDTO;
public ICarDataTransferObject GetDTO() { return _readOnlyDTO; }
public A(ICarDataTransferObject dto) {
_dto = new CarDataTransferObject(dto);
_readOnlyDTO = new ReadOnlyCarDataTransferObject(_dto);
}
}
You commonly see this approach in .NET applications.
While it is debatable whether your static method is an anti-pattern or not, it surely won't scale for combinations of different attributes. Nonetheless, even if it's not an anti-pattern, I think there is a better way to accomplish what you need.
There's a variant of the traditional builder pattern that, instead of creating a new empty builder, accepts an already built object and creates an already initialized builder. Once you create the builder this way, you simply change the length attribute in the builder. Finally, build the object. In plain code (no Lombok, sorry) it could be like this:
public class CarDataTransferObj {
private Integer id;
private String color;
// other attributes omitted for brevity
private Integer length;
// Private constructor for builder
private CarDataTransferObj(Builder builder) {
this.id = builder.id;
this.color = builder.color;
this.length = builder.length;
}
// Traditional factory method to create and return builder
public static Builder builder() {
return new Builder();
}
// Factory method to create and return builder initialized from an instance
public static Builder builder(CarDataTransferObj car) {
Builder builder = builder();
builder.id = car.id;
builder.color = car.color;
builder.length = car.length;
return builder;
}
// getters
public static class Builder {
private Integer id;
private String color;
private Integer length;
private Builder() { }
public Builder withId(Integer id) { this.id = id; return this; }
public Builder withColor(String color) { this.color = color; return this; }
public Builder withLength(Integer length) { this.length = length; return this; }
public CarDataTransferObj build() {
return new CarDataTransferObj(this);
}
}
}
Now with all this infrastructure in place, you can do what you want as easy as:
CarDataTransferObj originalCar = ... // get the original car from somewhere
CarDataTransferObj newCar = CarDataTransferObj.builder(originalCar)
.withLength(newLength)
.build();
This approach has the advantage that it scales well (it can be used to change any combination of parameters). Maybe all this builder's code seems boilerplate, but I use an IntelliJ plugin to create the builder with two keystrokes (including the variant factory method that accepts a built instance to create an initialized builder).
I'm still new to java but..
I guess making a copy method which takes the CarDataTransferObj object variables and sets their values to another CarDataTransferObj object variables and changing the the length using it's setter method would be better idea
Example:
public class CarDataTransferObj {
private Integer id;
private String color;
private String manufacturer;
private String model;
private String uniqueIdNr;
private Integer nrOfDoors;
private EngineType engineType;
private Integer length;
private Integer safetyLevel;
public void Copy(CarDataTransferObj copy) { //Could add another parameter here to be the new length
copy.setId(id);
copy.set(color);
copy.setManufacturer(manufacturer);
copy.setModel(model);
copy.setUniqueIdNr(uniqueIdNr));
copy.setNrOfDoors(nrOfDoors));
copy.setEngineType(engineType));
copy.setLength(length);
copy.setSafetyLevel(safetyLevel));
}
}
public class SomeOtherClass {
CarDataTransferObj car1 = new CarDataTransferObj(); //Using this way made you able to use the constructor for a more useful thing
//You set the variables you want for car1 here
CarDataTransferObj car2 = new CarDataTransferObj();
car1.Copy(car2)
car2.setLength(newLength) //Set the new length here
}

How can we create immutable class object using setter instead constructor.As I want to use its setter method .Does it Possible to make immutable?

Creating immutable class using setter method from outside class.As i have a POJO Class Object creation may be done using setter method.How come it possible to make immutable using setter
Setters are mutators.
https://en.wikipedia.org/wiki/Mutator_method
I think you might be referring to a factory method?
https://www.tutorialspoint.com/design_pattern/factory_pattern.htm
Or maybe you have some hybrid thingo going on.
People more experienced then me would have better answers.
You can use the Builder Pattern. There you have a separate builder class with a kind of setter for each field. The final build() eventually creates the immutable object.
public final class Person {
private final String forename;
private final String surename;
private final int age;
private Person(String forename, String surename, int age) {
this.forename = forename;
this.surename = surename;
this.age = age;
}
public String getForename() {
return forename;
}
public String getSurename() {
return surename;
}
public int getAge() {
return age;
}
public static PersonBuilder createBuilder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String forename;
private String surename;
private int age;
private PersonBuilder() {
}
public PersonBuilder withForename(String forename) {
this.forename = forename;
return this;
}
public PersonBuilder withSurename(String surename) {
this.surename = surename;
return this;
}
public PersonBuilder withAge(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(forename, surename, age);
}
}
You can then create a Person instance like so:
Person person = Person.createBuilder().withSurename("Krueger")
.withForename("Freddy").withAge(47).build();
With a builder you have the best of both worlds. The flexibility of setters (including fluent API) and immutable objects at the end.
Edit:
Joshua Bloch stated in Item 15: "Minimize Mutability" in his book "Effective Java":
To make a class immutable, follow these five rules:
Don’t provide any methods that modify the object’s state (known as mutators).
Ensure that the class can’t be extended. [...]
Make all fields final. [...]
Make all fields private. [...]
Ensure exclusive access to any mutable components. [...]
To fulfill point 2 I added the final keyword to the above Person class.
According to this widely accepted definition of immutability a class with setters is per se not immutable because it violates point 1.
If think the intention to ask this question in an interview is to see wether the candidate is able to recognize the discrepancy in the question itself and how far goes the knowledge about immutability and the various alternatives to create instances of immutable classes (per constructor, per static factory methods, per factory classes, per builder pattern, ...).

Decide which Enum return based on object properties

I'm wondering if there is some design pattern to help me with this problem.
Let's say I have a class Person which has three attributes: name, nickname and speaksEnglish and an Enum PersonType with TypeOne, TypeTwo and TypeThree.
Let's say if a Person has nickname and speaksEnglish it's a TypeOne. If it has nickame but doesn't speaksEnglish, it's a TypeTwo. If it does not have nickame, so it's TypeThree.
My first thought would have a method with some if-else and returning the related Enum. In the future I can have more attributes in Person and other types of PersonType to decide.
So, my first thought was create a method with a bunch of if (...) { return <PersonType> } or switch-case, but I was wondering if there is some design pattern I can use instead of ifs and switch-case.
I will recomend you to use just simple inheritance with immutable objects.
So, at first you have to create abstract class:
public abstract class AbstractPerson {
private final String name;
private final Optional<String> nickname;
private final boolean speaksEnglish;
private final PersonType personType;
protected AbstractPerson(final String name, final Optional<String> nickname, final boolean speaksEnglish, final PersonType personType) {
this.name = name;
this.nickname = nickname;
this.speaksEnglish = speaksEnglish;
this.personType = personType;
}
public String getName() {
return name;
}
public Optional<String> getNickname() {
return nickname;
}
public boolean getSpeaksEnglish() {
return speaksEnglish;
}
public PersonType getPersonType() {
return personType;
}
}
With PersonType enum:
public enum PersonType {
TypeOne, TypeTwo, TypeThree;
}
Now, we have three options with corresponding constructors in child classes:
public final class EnglishSpeakingPerson extends AbstractPerson {
public EnglishSpeakingPerson(final String name, final String nickname) {
super(name, Optional.of(nickname), true, PersonType.TypeOne);
}
}
public final class Person extends AbstractPerson {
public Person(final String name, final String nickname) {
super(name, Optional.of(nickname), false, PersonType.TypeTwo);
}
public Person(final String name) {
super(name, Optional.empty(), false, PersonType.TypeThree);
}
}
In this case, our concrete classes are immutable and its type is defined in moment of creation. You don't need to create if-else ladders - if you want to create new type, just create new class/constructor.
I don't think Type can really be an attribute of a Person. I am not against #ByeBye's answer but with that implementation you will still end up changing Person class when there are new types introduced.
X type of person is ultimately a person itself. Say a Manager or Developer are both employees of a company, so it makes a lot of sense to have them as specialized classes that derive from an Employee. Similarly in your case, having person type as an attribute and then doing all if-else stuff clearly violates SOLID.
I would instead have specific implementations of Person class and mark itself as an abstract one.
public abstract class Person {
public Person(string name) {
Name = name;
}
public abstract string Name { get; set; }
public abstract string NickName { get; set; }
public abstract bool SpeaksEnglish { get; set; }
}
public class TypeOnePerson : Person {
public TypeOnePerson(string name, string nickName) : base(name) {
NickName = nickName; // Validate empty/ null
}
SpeaksEnglish = true;
}
public class TypeTwoPerson : Person {
public TypeOnePerson(string name, string nickName) : base(name) {
NickName = nickName; // Validate empty/ null
}
SpeaksEnglish = false;
}
I also think that this question is language-agnostic, it is a pure design question. So please bear with me as the code above is in C#. That doesn't matter, however.
As far as OO principles are considered why to create object with combinations of optional attributes? If its question of one or two then Optional approach will remain maintainable, but type will be based on many combinations (in future code will be full of Boolean Algebra) and question also says "...In the future I can have more attributes in Person and other types of PersonType to decide.".
I would suggest approach of using Decorator pattern, which allows us to create customized objects with complete code reuse. Person will be Component and Optional attributes (they are types e.g NickName with validation as behavior) will be concrete decorators.
Any addition to Person and adding new Concrete Decorator type remain two separate concerns. Decorator Pattern is a best candidate for this kind of requirement. Its Intent from GOF book (by Erich gamma) pattern Catalog says - "Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality". [though for very small number of expected extensions earlier answers make more sense.]

Encapsulating builders in Java

I have 2 builders in my codebase, which can be accessed like this :
return new Developer.Builder("John", "Doe").age(30).build();
return new Manager.Builder("Eve", "Page").age(40).build();
I want to make the API simpler by encapsulating in an enum :
return Google.Developer.Builder("John", "Doe").age(30).build();
return Google.Manager.Builder("Eve", "Page").age(40).build();
My goal is to simplify the process for
Changing company names from Google to Microsoft
If a new role is added (apart from Developer and Manager), users of my code can know about it in one place.
Only option which comes to my mind is having company name as enum - but then I won't be able to implement builder pattern.
You can create an API similar to what you describe:
enum Google {
Developer, Manager;
public Builder builder(String name) {
return new Builder(this, name);
}
public static class Builder {
public Builder(Google role, String name) { ... }
public Builder age(int age) { ... }
public Employee build() { ... }
}
}
Now you can write
Employee e = Google.Developer.builder("John").age(30).build();
I don't see what the point is for all this. Do the builders somehow depend on the company and role in a non-trivial way?
If not, you can define the Builder as a separate class and use an interface to mark what ever represents roles in companies, similar to Sleiman's answer.
You could even parametrize the Employee class with company, if this makes sense in your application...
interface CompanyRole { /* just a marker */ }
enum Google implements CompanyRole {
...
Employee.Builder<Google> builder(String name) {
return new Employee.Builder<>(this, name);
}
}
class Employee<T extends CompanyRole> {
...
static class Builder<T extends CompanyRole> {
EmployeeBuilder(T role, String name) { ... }
Employee<T> build() { ... }
}
}
And you can still write
Employee<Google> e = Google.Developer.builder("John").age(30).build();
You can add an interface that represents a company
interface Company{
}
And have an enum of well known companies,
enum Companies implements Company{
GOOGLE,
MICROSOFT,
...
}
And now in your builder you can add a method that takes a Company rather an enum
Builder company(Company company){
addCompany(company);
return this;
}
And construct it fluently like this
Developer.Builder("John", "Doe").company(Companies.GOOGLE).age(30).build();
And now companies can either be constants or something you load from a db (anything that implements Company). It is type-safe either ways.
Review
return Google.Developer.DevBuilder("John", "Doe").age(30).build();
This makes no sense. Taking a closer look, above call leads to a class Google, which contains an inner class Developer. That class defines a static method called DevBuilder that takes 2 parameters, first and last name, and returns an instance of Builder/DeveloperBuilder.
This is not an object oriented, extensible approach. Even though you gave us very little context, I'd argue that companies are static objects, which are not subject to change. Referring to the example you made in the comments - a new company is more likely than a new CompressFormat.
Further, there is no possibility to change behaviour via polymorphism, except for the dynamic calls to age(int) and build().
Dynamic approach
Below a concept of a more dynamic approach (of course mechanics should be added, to make sure that there is only one object for a company, e.g. Company.byName("Google") etc.)
public static void main(String[] args) {
Company google = new Google();
Manager manager = google.newManager();
}
static abstract class Company {
public Manager newManager() {
return new ManagerBuilder("Eve", "Page").age(40).build();
}
}
static class Google extends Company {
}
You can easily add new companies and change the way a manager (or any other employee) is created, you can also use the default.
Refactoring
With some more playing around, you can remove the boiler plate code in the classes for employees and their corresponding builders, by creating two base classes as follows
static abstract class Person<P extends Person<P>> {
protected final String firstName;
protected final String lastName;
protected final int age;
public <T extends AbstractBuilder<P, T>> Person(AbstractBuilder<P, T> builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
}
}
static abstract class AbstractBuilder<P extends Person, T extends AbstractBuilder<P, T>> {
protected final String firstName;
protected final String lastName;
protected int age;
public AbstractBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
abstract T self();
abstract P build();
T age(int age) {
this.age = age;
return self();
}
}
Utilizing the above, creating a class Manager and its Builder yields following code
static class Manager extends Person<Manager> {
public <T extends AbstractBuilder<Manager, T>> Manager(AbstractBuilder<Manager, T> builder) {
super(builder);
}
}
static class ManagerBuilder extends AbstractBuilder<Manager, ManagerBuilder> {
public ManagerBuilder(String firstName, String lastName) {
super(firstName, lastName);
}
#Override
ManagerBuilder self() {
return this;
}
#Override
Manager build() {
return new Manager(this);
}
}
Managerand its Builder, or any other employee can be extended with more fields.

Possibilities of creating immutable class in Java

what are possibilities of creating immutable bean in Java. For example I have immutable class Person. What's a good way to create instance and fill private fields. Public constructor doesn't seems good to me because of a lot input parameters will occure as class will grow in rest of application. Thank you for any suggestions.
public class Person {
private String firstName;
private String lastName;
private List<Address> addresses;
private List<Phone> phones;
public List<Address> getAddresses() {
return Collections.unmodifiableList(addresses);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<Phone> getPhones() {
return Collections.unmodifiableList(phones);
}
}
EDIT: Specify question more precisely.
You could use the builder pattern.
public class PersonBuilder {
private String firstName;
// and others...
public PersonBuilder() {
// no arguments necessary for the builder
}
public PersonBuilder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Person build() {
// here (or in the Person constructor) you could validate the data
return new Person(firstName, ...);
}
}
You can then use it like this:
Person p = new PersonBuilder.firstName("Foo").build();
At first sight it might look more complex than a simple constructor with tons of parameters (and it probably is), but there are a few significant advantages:
You don't need to specify values that you want to keep at the default values
You can extend the Person class and the builder without having to declare multiple constructors or needing to rewrite every code that creates a Person: simply add methods to the builder, if someone doesn't call them, it doesn't matter.
You could pass around the builder object to allow different pieces of code to set different parameters of the Person.
You can use the builder to create multiple similar Person objects, which can be useful for unit tests, for example:
PersonBuilder builder = new PersonBuilder().firstName("Foo").addAddress(new Address(...));
Person fooBar = builder.lastName("Bar").build();
Person fooBaz = builder.lastName("Baz").build();
assertFalse(fooBar.equals(fooBaz));
You should have a look at the builder pattern.
One good solution is to make your fields final, add your constructor private and make use of Builders in your code.
In our project we combined the Builder pattern with a validation framework so that once an object is created we are sure it's immutable and valid.
Here is a quick example:
public class Person {
public static class Builder {
private String firstName;
private String lastName;
private final List<String> addresses = new ArrayList<String>();
private final List<String> phones = new ArrayList<String>();
public Person create() {
return new Person(firstName, lastName, addresses, phones);
}
public Builder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder addAddresse(String adr) {
if (adr != null) {
addresses.add(adr);
}
return this;
}
public Builder addPhone(String phone) {
if (phone != null) {
phones.add(phone);
}
return this;
}
}
// ************************ end of static declarations **********************
private final String firstName;
private final String lastName;
private final List<String> addresses;
private final List<String> phones;
private Person(String firstName, String lastName, List<String> addresses, List<String> phones) {
this.firstName = firstName;
this.lastName = lastName;
this.addresses = addresses;
this.phones = phones;
}
public List<String> getAddresses() {
return Collections.unmodifiableList(addresses);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<String> getPhones() {
return Collections.unmodifiableList(phones);
}
}
In my example you can see that all the setters in the Builder return the Builder instance so that you can easily chain the setters calls. That's pretty useful.
You could take a look at the Builder pattern presented by Joshua Bloch.
As I said before, combined with a validation framework (see for ex. http://www.hibernate.org/subprojects/validator.html) this is really powerfull.
With interfaces. Do this:
public interface Person {
String getFirstName();
String getLastName();
// [...]
}
And your implementation:
// PersonImpl is package private, in the same package as the Factory
class PersonImpl {
String getFirstName();
void setFirstName(String s);
String getLastName();
void setLastName(String s);
// [...]
}
// The factory is the only authority to create PersonImpl
public class Factory {
public static Person createPerson() {
PersonImpl result = new PersonImpl();
// [ do initialisation here ]
return result;
}
}
And never expose the implementation to the places where you want Person to be immutable.
Initializing in the constructor is nevertheless the simplest and safest way to achieve immutability, as this is the only way to have final fields in your immutable class (which is the standard idiom, and has beneficial effects especially if your class is used in a multithreaded environment). If you have lots of properties in your class, it may be a sign that it is trying to do too much. Consider dividing it to smaller classes, or extracting groups of related properties into compound property classes.
Using a Builder (with a private constructor) is a possibility, however it still needs a way to set the properties of the object being built. So you fall back to the original dilemma of constructor parameters vs accessing the private members. In the latter case you can't declare the properties of the object being built as final, which IMHO is a great minus. And in the former case you still have the same long list of constructor parameters you wanted to avoid in the first place. Just now with a lot of extra boilerplate code on top of it.
You can achieve an "immutable" bean by making a read-only interface and then making the implementation into a mutable bean. Passing around the interface won't allow for mutation, but when you construct the object and have the implementation, you can do all sorts of bean-y things:
public interface Person {
String getFirstName();
String getLastName();
// ... other immutable methods ...
}
public class MutablePerson implements Person {
// ... mutable functions, state goes here ...
}
Use the factory-pattern:
let Person be an interface with only "get"-functions
create a PersonFactory with an appropriate API for building a Person-object
the PersonFactory creates an object which implements the Person-interface and returns this
Have final fields.
Make the class as "final" class by declaring as final public class Person
do not use setXXX() methods to set the value since it will change the state of a variable. however getXXX() methods are allowed.
Use a private constructor so that you can set fields using the constructor itself.
Follow the above guidelines for Immutable class.
Use final fields for all your instance variables. You can create a constructor if you like and choose to not expose setters, e.g.,
public class Person {
private final String firstName;
....
public Person(String firstName, ... ) {
this.firstName = firstName;
}
}

Categories