Builder Pattern: which variant is preferred? [closed] - java

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I was going through Effective Java book , and creating notes for my future reference ,
i came across Builder Pattern.
Well i understood what it is and how its suppose to be used.In the process i created a two example variations of the builder pattern.
I would need help in listing down the differences and the advantage each has?
Well i certainly noticed that , Example 1 exposes less methods , there by less restrictive and
more generic , there by allowing it to be used more flexibly.
Please point out other things i have missed?
Example 1
package item2;
/**
* #author Sudhakar Duraiswamy
*
*/
public class Vehicle {
private String type;
private int wheels;
interface Builder<T>{
public T build();
}
public static class CarBuilder implements Builder<Vehicle>{
private String type;
private int wheels;
CarBuilder createVehicle(){
this.type= "Car";
return this;
}
CarBuilder addWheels(int wheels){
this.wheels = wheels;
return this;
}
public Vehicle build(){
Vehicle v = new Vehicle();
v.type = type;
v.wheels = wheels;
return v;
}
}
public static class TruckBuilder implements Builder<Vehicle>{
private String type;
private int wheels;
TruckBuilder createVehicle(){
this.type= "Truck";
return this;
}
TruckBuilder addWheels(int wheels){
this.wheels = wheels;
return this;
}
public Vehicle build(){
Vehicle v = new Vehicle();
v.type = type;
v.wheels = wheels;
return v;
}
}
public Vehicle(){
}
public static void main(String[] args) {
//This builds a car with 4 wheels
Vehicle car = new Vehicle.CarBuilder().createVehicle().addWheels(4).build();
//THis builds a Truck with 10 wheels
Vehicle truck = new Vehicle.TruckBuilder().createVehicle().addWheels(10).build();
}
}
Example 2
package item2;
/**
* #author Sudhakar Duraiswamy
*
*/
public class Vehicle2 {
private String type;
private int wheels;
interface Builder<T>{
public T build();
public String getType();
public int getWheels() ;
}
public static class CarBuilder implements Builder<Vehicle2>{
private String type;
private int wheels;
public String getType() {
return type;
}
public int getWheels() {
return wheels;
}
CarBuilder createVehicle(){
this.type= "Car";
return this;
}
CarBuilder addWheels(int wheels){
this.wheels = wheels;
return this;
}
public Vehicle2 build(){
return new Vehicle2(this);
}
}
public static class TruckBuilder implements Builder<Vehicle2>{
private String type;
private int wheels;
public String getType() {
return type;
}
public int getWheels() {
return wheels;
}
TruckBuilder createVehicle(){
this.type= "Truck";
return this;
}
TruckBuilder addWheels(int wheels){
this.wheels = wheels;
return this;
}
public Vehicle2 build(){
return new Vehicle2(this);
}
}
public Vehicle2(Builder<? extends Vehicle2> builder){
Vehicle2 v = new Vehicle2();
v.type = builder.getType();
v.wheels = builder.getWheels();
}
public Vehicle2(){
}
public static void main(String[] args) {
//This builds a car with 4 wheels
Vehicle2 car = new Vehicle2.CarBuilder().createVehicle().addWheels(4).build();
//THis builds a Truck with 10 wheels
Vehicle2 truck = new Vehicle2.TruckBuilder().createVehicle().addWheels(10).build();
}
}

None of the above.
The first one doesn't allow building an immutable Vehicle, which is often why the Builder pattern is used.
The second example is a variation of the first one which allows getting information from the builder using additional getter methods. But those those methods aren't used anywhere, except in the Vehicle constructor, which has access to the builder fields directly. I don't see the point in adding them.
I see two more important things to improve:
The two builder types do exactly the same thing. There's no need for two types. A single one is sufficient.
What the createVehicle() method does should be done by the builder constructor. If you construct a CarBuilder, it's obviously to build a car, so the type of the vehicle should be set as soon as the builder is constructed. Here's how I would write it:
.
public final class Vehicle {
private final String type;
private final int wheels;
private Vehicle(Builder builder) {
this.type = builder.type;
this.wheels = builder.wheels;
}
public static Builder carBuilder() {
return new Builder("car");
}
public static Builder truckBuilder() {
return new Builder("truck");
}
public static class Builder {
private final String type;
private int wheels;
private Builder(String type) {
this.type = type;
}
public Builder addWheels(int wheels){
this.wheels = wheels;
return this;
}
public Vehicle build() {
return new Vehicle(this);
}
}
public static void main(String[] args) {
Vehicle car = Vehicle.carBuilder().addWheels(4).build();
Vehicle truck = Vehicle.truckBuilder().addWheels(10).build();
}
}

There is a third variant too, with less code:
Instead of having their own instance fields the builders could also mutate the state of Vehicle. Inner classes can write private members of their outer class:
class Vehicle {
private int wheels;
private Vehicle() {}
public static class Builder {
private boolean building = true;
private Vehicle vehicle = new Vehicle();
public Builder buildWheels(int wheels) {
if(!this.building) throw new IllegalStateException();
this.vehicle.wheels = wheels;
return this;
}
public Vehicle build() {
this.building = false;
return this.vehicle;
}
}
}
Since the fields are private and you allow it to be build only once (building flag), built Vehicle instances are still immutable to consumers even though the fields cannot be final anymore (no more realio-trulio immutability, see Eric's blog article which is on C# but the concepts are similar).
You need to be more careful as non-final fields do not have to be initialized during object construction (enforced by the compiler) and you must check the building state carefully. You do however save a full extra-copy of all instance fields. In general, this is useful if you have a rather large set of instance variables that are built with rather few methods, where each method builds a few fields at once.
I know this does not point out any advantages or drawbacks of your approaches. However, this approach can save a lot of extra code if you do not need the fields to be final.

Related

Should I keep an enum attribute when it has always the same value as a result of a new inheritance?

I have these classes:
enum Brand {
FORD, FERRARI, TESLA, RENAULT;
}
public class Car {
Brand brand;
String plate;
...
}
//getters and setters
Imagine that for some reason, I need to make Car a superclass for two new classes: CombustionCar and ElectricCar. One of the new requierements is that ElectricCar's brand attribute must be always TESLA value and not any of the other ones values.
I've thougth some solutions:
I could keep Brand attr on superclass Car, and make ElectricCar constructor to set TESLA brand. But this way could allow me to set a new Brand after creating the object
public class ElectricCar extends Car {
public ElectricCar(...){
super(Brand.TESLA, ...);
}
ElectricCar ec = new ElectricCar(...);
ec.setBrand(Brand.FORD);
I can take Brand attr out from superclass and set it on both subclasses, but setting it in ElectricCar as a class attribute with a final so anyone would be able to set a new value
public class ElectricCar extends Car {
public static final Brand brand = Brand.TESLA;
...
}
public class CombustionCar extends Car {
private Brand brand;
...
}
Avoid inheritance and use composition, but with this I wont be able to use, for example, a List which contain both:
public class ElectricCar {
private Car car;
private Brand brand = Brand.TESLA;//with no setter
...
}
public class CombustionCar {
private Car car;
private Brand brand;
...
}
I'm asking for the most elegant and manteinable solution, I think any of them would be nice to resolve my problem.
Your first solution is incorrect given that you required a non editable BRAND for an electric car.
Your second solution just doesn't work at all excepted if you override both getter and setter of brand field to use your static field, which is not "elegant and mantainable"
Your third solution doesn't make use of object oriented concept.
A simple solution I would use is to let the field brand and its getter in Car superclass, but I'd only define the setter in the CombustionCar class.
Alternatively, if you extend your model, you could create an intermediate abstract superclass "FreeBrandCar" which implements the setter.
Solution with the setter in CombustionCar
abstract public class Car {
protected String brand;
protected Car(final String b) {
this.brand = b;
}
public String getBrand() {
return this.brand;
}
}
public class ElectricCar extends Car {
public ElectricCar() {
super("Tesla");
}
}
public class CombustionCar extends Car {
public CombustionCar(final String b) {
super(b);
}
public void setBrand(final String b) {
this.brand = b;
}
}
Solution with an intermediate class
abstract public class Car {
protected String brand;
protected Car(final String b) {
this.brand = b;
}
public String getBrand() {
return this.brand;
}
}
abstract public class FreeBrandCar extends Car {
public FreeBrandCar (final String b) {
super(b);
}
public void setBrand(final String b) {
this.brand = b;
}
}
public class ElectricCar extends Car {
public ElectricCar() {
super("Tesla");
}
}
public class CombustionCar extends FreeBrandCar {
public CombustionCar(final String b) {
super(b);
}
}
It respects your requirements :
public void test() {
ElectricCar ec = new ElectricCar();
ec.setBrand("..."): // Doesn't compile
CombustionCar cc = new CombustionCar("Ford"); // OK
cc.setBrand("Fiat"); // OK
Arrays.asList(ec, cc)
.stream()
.forEach(car -> System.out.println(car.getBrand())); // prints Tesla and Fiat
}

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
}

Easy access Object Getter with Java

Method 1: traditional getter/setter
Toyota class:
public class ToyotaCar implements Serializable {
private static final long serialVersionUID = 2011932556974180375L;
private int miles;
public void addMiles(int miles){
this.miles = miles;
}
public int getMiles(){
return miles;
}
}
Human class:
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private ToyotaCar car;
public void setCar(ToyotaCar car){
this.car = car;
}
public int getCar(){
return car;
}
public void addCarMiles(int num){
getCar().addMiles(num);
}
}
Method 2: "other"
Toyota class: -same as above toyota class-
Additional containerHandler class:
public enum HumanContentsContainer {
CAR{
#Override public Object getContainer(){
return new ToyotaCar();
}
},
HOUSE;
public Object getContainer(){ //because cannot be static enum constant as every human has different items
return null;
}
}
Human class:
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private HashMap<HumanContentsContainer, Object> contents;
public void setContents(){
for (HumanContentsContainer c : HumanContentsContainer.values()){
contents.put(c, c.getContainer());
}
}
public HashMap<HumanContentsContainer, Object> getContents(){
return contents;
}
public void addCarMiles(int num){
//TODO how to replicate this: getCar().addMiles(num);???
}
//TODO i dont want to use the below method because whats the point of creating a whole container handler if im just going to use a traditional getter again?
//public ToyotaCar getCar(){
// return (ToyotaCar) contents.get(HumanContentsContainer.CAR);
// }
}
So how do I replicate the getCar().addMiles(x) method using a traditional getter without actually creating a getter?
Please note I also don't want to do this (below code): Because again, not worth it over a getter then:
public void addCarMiles(int num){
((ToytotaCar)contents.get(HumanContentsContainer.CAR).addMiles(num);
}
Looking for some easy kind of usage like:
human.getContentsThatIsIntanceOf(ToyotaCar).addMiles(1);
But don't know what getContentsThatIsInstanceOf would look like
I would go with:
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private ToyotaCar car;
public void setCar(ToyotaCar car){
this.car = car;
}
public int getCar(){
return car;
}
public void addCarMiles(int num){
getCar().addMiles(num);
}
public Map<HumanContentsContainer, Object> getContents(){
Map<HumanContentsContainer, Object>map = new HashMap();
map.put(CAR,this.car );
//same for all the shoes and clothes and whatever the Human has
}
public void setContents(){
for (HumanContentsContainer c : HumanContentsContainer.values()){
switch (c){
case CAR:{
this.car=c.getContainer();
}
}
//and so on
}
}
}
Edit
If you need to have a dynamic set of capabilities, I would suggest that you indeed keep the map of objects, and get rid of the ‘addCarMiles‘ method, as it implies that every human has a car.
I would implement public method on human ‘performCommand(CapabilityType, CapabilityCommand)‘ where the command will receive the capability and perform the operation on it. You may check out the Command Pattern tutorials.
Edit 2:
If all you want is to create a getter which will return dynamic type, you can use generics.
import java.io.Serializable;
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private HashMap<Class, Object> contents;
public void setContents(){
for (HumanContentsContainer c : HumanContentsContainer.values()){
contents.put(c.getContainer().getClass(), c.getContainer());
}
}
public HashMap<Class, Object> getContents(){
return contents;
}
public <T> T getContentsThatIsIntanceOf(Class<T> type){
Object object = contents.get(type);
if (object==null){
throw new NoSuchElementException("No such element: "+type.getName());
}
return type.cast(object);
}
public void usageExample(){
this.getContentsThatIsIntanceOf(ToyotaCar.class).addMiles(10);
}
}

How to extend or implement classes? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Picture to show task:
First I am sorry, for my bad to for expressing my mind.
I have such a task, I don't need that you do it for me.
Vehicle is parent class for Sedan (Cause Sedan class is String type).
How to extend or implement Vehicle class with universal class?
I forgot to ask my teacher, but maybe you will know, what means striped pointer to Owner class, and what is that: has a?
P.S. If you need code that I have written already, I will show you.
So this is my parent Vehicle class:
public class Vehicle {
private int vehicleNumber;
protected int fuelTankSize;
protected int maxSpeed;
protected Owner owner;
//1
public Vehicle(int vehicleNumber){
this.vehicleNumber = vehicleNumber;
}
//2
public Vehicle(int vehicleNumber, int fuelTankSize) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
}
//3
public Vehicle(int vehicleNumber, int fuelTankSize, int maxSpeed) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
this.maxSpeed = maxSpeed;
}
//4
public Vehicle(int vehicleNumber, int fuelTankSize, int maxSpeed, Owner owner) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
this.maxSpeed = maxSpeed;
this.owner = owner;
}
//1
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed (int maxSpeed){
this.maxSpeed = maxSpeed;
}
//2
protected int getFuelTankSize(){
return fuelTankSize;
}
protected void setFuelTankSize (int fuelTankSize){
this.fuelTankSize = fuelTankSize;
}
//3
public Owner getOwner(){
return owner;
}
public void setOwner (Owner owner){
this.owner = owner;
}
}
child Sedan with:
public class Sedan extends Vehicle {
private String registrationIndex;{
}
public Sedan (int vehicleNumber, int fuelTankSize, int maxSpeed, String registrationIndex, Owner owner) {
super(vehicleNumber, fuelTankSize, maxSpeed, owner);
this.setRegistrationIndex (registrationIndex);
}
public String getRegistrationIndex (){
return registrationIndex;
}
public void setRegistrationIndex (String registrationIndex) {
this.registrationIndex = registrationIndex;
}
}
second Universal child without an error:
public class Universal extends Vehicle {
private int trunkSize;
public Universal (int vehicleNumber, int fuelTankSize, int maxSpeed, int trunkSize, Owner owner) {
super(vehicleNumber, fuelTankSize, maxSpeed, owner);
this.setTrunkSize (trunkSize);
}
public int getTrunkSize() {
return trunkSize;
}
public void setTrunkSize(int trunkSize) {
this.trunkSize = trunkSize;
}
public void printDescription() {
super.printDescription();
System.out.println("Universalo bagažinės tūris: " + getTrunkSize() + "l.");
}
}
and some misterious (to me) Owner class:
public class Owner {
public String firstName;
public String lastName;
public Owner (String firstName){
this.firstName = firstName;
}
public Owner (String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
}
added VechileTest for testing:
public class VehicleTest {
public static void main(String[] args) {
Vehicle vehicleInf = new Vehicle (1, 45, 260);
Universal universalInf = new Universal(2, 50, 220, 70);
Sedan sedanInf = new Sedan (3, 40, 180, "AVA 123");
vehicleInf.printDescription();
universalInf.printDescription();
sedanInf.printDescription();
}
}
Well, 1st of all I recommend you read a good tutorial / explanation of UML class diagrams, like this here for example.
After you know the basics, it should be easy to translate that into Java code.
I'll give you the code for the Universal class and a start for your Vehicle. The rest you'll have to do on your own.
The class Universal:
public class Universal extends Vehicle {
private int trunkSize;
public int getTrunkSize() {
return this.trunkSize;
}
public void setTrunkSize(int trunkSize) {
this.trunkSize = trunkSize;
}
}
As you can see the first block inside a class box refers to the variables. The - and + indicates the visibility (private for -, public for +).
The next block is about the methods, specifying visibility, return type, method name and parameters (type and name).
The arrow between Universal and Vehicle indicates a inheritance relationship (see in code that Universal extends Vehicle).
So all in all the diagram is a construction plan for your classes; at least for the static part, meaning the relationships and state they can have.
The start of class Vehicle:
public class Vehicle {
private int vehicleNumber;
// the rest here ...
}
Edit:
Well, now that I see your code, you seem to have a few misconceptions:
The Sedan type is not from type String, it is from type Sedan (which extends Vehicle). Just the new member variable in the Sedan type is of type String, does not matter.
To your 1st question: The Vehicle class is the base (parent) class of Sedan. You do not to do anything with it, inheritance is expressed from the child towards the parent, not the other way around. Vehicle should usually be declared abstract (as you cannot create an instance of a generic Vehicle), but this is not in the diagram.
To your 2nd question: The has a relationship is just this. It expressed that one class has another class as it's member (which is redundantely expressed inside the class diagram already), so nothing to do for that.
Additionally your code has a few issues:
I do not see any constructors declared in Vehicle class, those 4 can go.
Your Sedan has a superflous pair of {} after declaration of your registrationIndex variable.
Since your Vehicle has no default constructor, you must call this constructor from your Sedan class (or remove the constructors from Vehicle.
Your Universal class calls the Vehicle constructor with the trunkSize while the Vehicle constructor expects the vehicleNumber there.
Your Vehicle class doesn't have a parameterless constructor, which means that Universal and Sedan must explicitly call one of them (super(...);). You're doing this in Universal (albeit incorrectly as you're passing the trunk size instead of the vehicle number expected by Vehicle's constructor) but not in Sedan.
As for the second question: The two major relations in OOP are is a and has a. The difference can be easily explained like this:
A Sedan is a vehicle
A vehicle has an owner
is a means it inherits some properties of something else, has a means that it has a reference to something else.

Builder Pattern in Effective Java

I have recently started to read Effective Java by Joshua Bloch. I found the idea of the Builder pattern [Item 2 in the book] really interesting. I tried to implement it in my project but there were compilation errors. Following is in essence what I was trying to do:
The class with multiple attributes and its builder class:
public class NutritionalFacts {
private int sodium;
private int fat;
private int carbo;
public class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder(int s) {
this.sodium = s;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
Class where I try to use the above class:
public class Main {
public static void main(String args[]) {
NutritionalFacts n =
new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
}
}
I am getting the following compiler error:
an enclosing instance that contains
effectivejava.BuilderPattern.NutritionalFacts.Builder
is required
NutritionalFacts n = new
NutritionalFacts.Builder(10).carbo(23).fat(1).build();
I do not understand what the message means. Please explain. The above code is similar to the example suggested by Bloch in his book.
Make the builder a static class. Then it will work. If it is non-static, it would require an instance of its owning class - and the point is not to have an instance of it, and even to forbid making instances without the builder.
public class NutritionFacts {
public static class Builder {
}
}
Reference: Nested classes
You should make the Builder class as static and also you should make the fields final and have getters to get those values. Don't provide setters to those values. In this way your class will be perfectly immutable.
public class NutritionalFacts {
private final int sodium;
private final int fat;
private final int carbo;
public int getSodium(){
return sodium;
}
public int getFat(){
return fat;
}
public int getCarbo(){
return carbo;
}
public static class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder sodium(int s) {
this.sodium = s;
return this;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
And now you can set the properties as follows:
NutritionalFacts n = new NutritionalFacts.Builder().sodium(10).carbo(15).
fat(5).build();
To generate an inner builder in Intellij IDEA, check out this plugin: https://github.com/analytically/innerbuilder
You are trying access a non-static class in a static way. Change Builder to static class Builder and it should work.
The example usage you give fails because there is no instance of Builder present. A static class for all practical purposes is always instantiated. If you don't make it static, you'd need to say:
Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build();
Because you would need to construct a new Builder every time.
You need to declare the Builder inner class as static.
Consult some documentation for both non-static inner classes and static inner classes.
Basically the non-static inner classes instances cannot exist without attached outer class instance.
Once you've got an idea, in practice, you may find lombok's #Builder much more convenient.
#Builder lets you automatically produce the code required to have your class be instantiable with code such as:
Person.builder()
.name("Adam Savage")
.city("San Francisco")
.job("Mythbusters")
.job("Unchained Reaction")
.build();
Official documentation: https://www.projectlombok.org/features/Builder
This mean that you cant create enclose type. This mean that first you have to cerate a instance of "parent" class and then from this instance you can create nested class instances.
NutritionalFacts n = new NutritionalFacts()
Builder b = new n.Builder(10).carbo(23).fat(1).build();
Nested Classes
The Builder class should be static. I don't have time right now to actually test the code beyond that, but if it doesn't work let me know and I'll take another look.
I personally prefer to use the other approach, when you have 2 different classes. So you don't need any static class. This is basically to avoid write Class.Builder when you has to create a new instance.
public class Person {
private String attr1;
private String attr2;
private String attr3;
// package access
Person(PersonBuilder builder) {
this.attr1 = builder.getAttr1();
// ...
}
// ...
// getters and setters
}
public class PersonBuilder (
private String attr1;
private String attr2;
private String attr3;
// constructor with required attribute
public PersonBuilder(String attr1) {
this.attr1 = attr1;
}
public PersonBuilder setAttr2(String attr2) {
this.attr2 = attr2;
return this;
}
public PersonBuilder setAttr3(String attr3) {
this.attr3 = attr3;
return this;
}
public Person build() {
return new Person(this);
}
// ....
}
So, you can use your builder like this:
Person person = new PersonBuilder("attr1")
.setAttr2("attr2")
.build();
As many already stated here you need to make the class static.
Just small addition - if you want, there is a bit different way without static one.
Consider this. Implementing a builder by declaring something like withProperty(value) type setters inside the class and make them return a reference to itself. In this approach, you have a single and an elegant class which is a thread safe and concise.
Consider this:
public class DataObject {
private String first;
private String second;
private String third;
public String getFirst(){
return first;
}
public void setFirst(String first){
this.first = first;
}
...
public DataObject withFirst(String first){
this.first = first;
return this;
}
public DataObject withSecond(String second){
this.second = second;
return this;
}
public DataObject withThird(String third){
this.third = third;
return this;
}
}
DataObject dataObject = new DataObject()
.withFirst("first data")
.withSecond("second data")
.withThird("third data");
Check it out for more Java Builder examples.
You need to change Builder class to static class Builder. Then it will work fine.
The other solutions double the memory allocation to instantiate the object. The following solution does not have that problem.
public class NutritionalFacts{
private int sodium;
private int fat;
private int carbo;
private NutritionalFacts(){}
public int getSodium(){ return sodium;}
public int getFat(){ return fat;}
public int getCarbo(){ return carbo;}
public static class Builder{
private NutritionalFacts nutrionalFacts;
public Builder(){
nutrionalFacts = new NutritionalFacts();
}
public Builder sodium(int s){
nutrionalFacts.sodium = s;
return this;
}
public Builder fat(int f){
nutrionalFacts.fat = f;
return this;
}
public Builder carbo(int c){
nutrionalFacts.carbo = c;
return this;
}
public NutritionalFacts build(){
return nutrionalFacts;
}
}
}

Categories