Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Let's assume we have User and UserBuilder class in their own package, that we want to be immutable and at consistent state before initialization, defined as follows:
public class User {
private final String firstName, lastName;
private final int age;
private final String adress;
protected User(UserBuilder buildUser) { //constructor acessible only in same packge
this.firstName = buildUser.lastName;
this.lastName = buildUser.lastName;
this.age = buildUser.age;
this.adress = buildUser.adress;
}
public String getFirstName() {
return firstName;
}
... // and other getters
}
And the builder class as follows:
public class UserBuilder {
public final String firstName;
public final String lastName;
public int age;
public String adress;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder setAge(int age) {
this.age = age;
return this;
}
public UserBuilder setAdress(String adress) {
this.adress = adress;
return this;
}
public UserBuilder getUser() {
return this;
}
public User build() {
return new User(getUser());
}
}
And finally we build the user in class that is in another package:
public static void main(String[] args) {
User user = new UserBuilder("John","Doe")
.setAge(22)
.build();
// User user = new User(UserBuilder) //error protected constructor
}
Is this considered safe and good design? If not, why?
My suggestions:
Place the Builder inside the User, so it is more trivial what the
Builder builds and User can access the private fields of the
Builder, therefore no getter needed in the builder.
Make User constructor private, because protected means derived classes can access the constructor, so immutability can broke.
the getUser() method is unnecessary.
Here is my example:
public final class User {
private final String firstName, lastName;
private final int age;
private final String address;
private final List<User> friends;
private User(Builder builder) {
this.firstName = builder.lastName;
this.lastName = builder.lastName;
this.age = builder.age;
this.address = builder.address;
this.friends = Collections.unmodifiableList(new ArrayList<>(builder.friends)); //immutable list
}
public String getFirstName() {
return firstName;
}
public List<User> getFriends() {
return friends;
}
/**
* other getters;
*/
public static class Builder {
private String firstName, lastName;
private int age;
private String address;
private List<User> friends = new ArrayList<>();
public Builder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setAddress(String address) {
this.address = address;
return this;
}
public Builder addFriend(User friend) {
this.friends.add(friend);
return this;
}
public User build() {
return new User(Builder.this);
}
}
public static void main(String[] args) {
User johnSmith = new User.Builder("John", "Smith").setAge(33).setAddress("New York").build();
}
}
Place UserBuilder inside User
Create constructor of User taking first/last name, address, age
Make constructor of User private
protected is not accessible ONLY in the same package, but in sub-classes as well.
Include the Builder class as nested class in User.
This approach is described here.
You are retrieving inmutable object, so this is right. But you are creating a User object aware of the builder object, and I think this is not right because the User class does not have to know that there is a builder class, you are coupling the two classes, i mean, User depends directly on UserBuilder, without UserBuilder User can not compile and this is not a good design
I Think you would have a better design following the another answers to the questions, with those examples you will delete the classes coupling
Related
This question already has answers here:
How to achieve method chaining in Java?
(4 answers)
Closed 6 years ago.
There is a coding style that I've seen a lot in Android Programming when using Google Services libraries where they use dots to call methods after initializing an instance of a class.
For example, lets say I have a Person class:
public class Person {
private String firstName;
private String lastName;
private String occupation;
private String primarySkill;
private String secondarySkill;
/* ******************
* CONSTRUCTOR
* ******************/
public Person(String firstName, String lastName) {
setFirstName(firstName);
setLastName(lastName);
}
/* ******************
* MUTATORS
* ******************/
// firstName Setter:
public void setFirstName(String firstName) {
this.firstName = firstName;
}
// lastName Setter:
public void setLastName(String lastName) {
this.lastName = lastName;
}
// occupation Adder:
public void addOccupation(String occupation) {
this.occupation = occupation;
}
// primarySkill Adder:
public void addPrimarySkill(String primarySkill) {
this.primarySkill = primarySkill;
}
// secondarySkill Adder:
public void addSecondarySkill(String secondarySkill) {
this.secondarySkill = secondarySkill;
}
}
Now, when I create an instance of this class, I want to be able to do the following:
Person bob = new Person("Bob", "Anderson")
.addOccupation("Student")
.addPrimarySkill("Java")
.addSecondarySkill("SQL");
However this gives me syntax errors. How can I build a class that can allow me to do this?
What you're looking for is called Method Chaining. Modify your setters to return this:
// occupation Adder:
public Person addOccupation(String occupation) {
this.occupation = occupation;
return this;
}
You should have "setter" methods returning the type of the object. To build on your addXyx methods:
public Person setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public Person addOccupation(String occupation) {
this.occupation = occupation;
return this;
}
public Person addPrimarySkill(String primarySkill) {
this.primarySkill = primarySkill;
return this;
}
public Person addSecondarySkill(String secondarySkill) {
this.secondarySkill = secondarySkill;
return this;
}
With that, you could chain your setter invocations:
Person bob = new Person("Bob", "Anderson")
.addOccupation("Student")
.addPrimarySkill("Java")
.addSecondarySkill("SQL");
This is a typical case of using a Builder Pattern. The setters in the builder pattern return this
I've been trying to keep coupling down in my code, but I think I may not fully understand it. My basic understanding is that coupling is "how dependent classes are on each other and know about the behavior of each other." I know that dependency injection is one way to reduce coupling and IoC.
The following is an quick example I came up of a Student, Professor, and Course. A course has a list of students and a professor. I have a controller (using MVC) that injects the Student and Professor objects.
Would the following still be considered coupled, or tightly coupled? This also would be an example of DI, correct?
Student class
public class Student {
private String firstName;
private String lastName;
private int studentID;
private int address;
private int telephone;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
}
Professor Class
public class Professor {
private String firstName;
private String lastName;
private int professorID;
private int address;
private int telephone;
private int salary;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getProfessorID() {
return professorID;
}
public void setProfessorID(int professorID) {
this.professorID = professorID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
Course Class
import java.util.List;
public class Course {
private List<Student> students;
private Professor professor;
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
I have a controller (using MVC) that injects the Student and Professor objects. Would the following still be considered coupled, or tightly coupled?
Since all references are Classes, you have a tightly coupled design. A good approach is to use interfaces in your code. This will allow you to change implementation any time you want and it will not affect the rest of your application.
This also would be an example of DI, correct?
If your Course, Professor and Student are configured beans, and you specify somewhere how to inject instances during bean instantiation, it will be a DI example. By now it is just three POJO classes.
What you have put here seem to be the Model part of your MVC implementation which have limited functionality other than setter-getters. To have a good example of decoupling and DI, you probably have Model, View and Controller classes that implement some interfaces. They are decoupled as each class's implementation is not aware/dependent on the other implementations. They only relate based on interfaces that well encapsulate and isolate components.
Probably you also have some fake/test implementation of those interfaces too
Then, there is a IoC setup that controls what implementation of each component will be resolved.
I want to know if my implementation of the builder object has disadvantages compared to the builder object implementation I see on most site's. I know it's overkill to implement a builder object for a class with only 2 fields, but these are just examples and meant to be small.
My implementation:
public class User {
private String firstname;
private String lastname;
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
private User(){}
public static class Builder{
private final User user;
public Builder(){
user = new User();
}
public Builder firstname(String firstname){
user.firstname = firstname;
return this;
}
public Builder lastname(String lastname){
user.lastname = lastname;
return this;
}
public User build(){
return user;
}
}
}
Builder object as found on the internet (example1 example2):
public class User {
private String firstname;
private String lastname;
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
private User(Builder builder){
this.firstname = builder.firstname;
this.lastname = builder.lastname;
}
public static class Builder{
private String firstname;
private String lastname;
public Builder firstname(String firstname){
this.firstname = firstname;
return this;
}
public Builder lastname(String lastname){
this.lastname = lastname;
return this;
}
public User build(){
return new User(this);
}
}
}
The second implementations seems cumbersome, cause the builder needs to have exactly the same field as the object it will be building (read: writing the same code twice).
It also seems more naturally (to me) that the builder creates the new User and populates its fields, instead off calling the constructor of the User with it's own instance.
Both examples can be tested with:
public static void main(String[] args) {
User u = new User.Builder().firstname("Tom").lastname("Jonckheere").Build();
System.out.println(u.getFirstname());
System.out.println(u.getLastname());
}
So my question is:
What are the disadvantages of my implementation of the builder object? I can't really tell any (and I'm not saying there aren't any) so I would like to hear some feedback! Or is my code also a valid implementation of the builder object?
The difference in the implementations are that if you want to create multiple equal (or similar) but not same objects, you'll have to create a new Builder whereas with the other implementation you can do this:
Builder b = new User.Builder();
User john = b.firstName("John").lastName("Smith").build();
User jack = b.firstName("Jack").build();
Good day,
I am new to JAVA'm learning this language and what I have learned it seems a fantastic language. My question is in relation to the following:
Suppose I have a class like this:
public class Person{
private String firstName;
private String lastName;
private int age;
private String entireName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEntireName() {
return entireName;
}
public void setEntireName(String entireName) {
this.entireName = entireName;
}
public static void Main(String args[]){
Person person = new Person();
person.setFirstName("Jhon");
person.setLastName("Adams");
person.setAge(20);
//Atention this line
person.setEntireName(person.getFirstName()+person.getLastName());
}
}
The language allows me to do this: person.setEntireName(person.getFirstName()+person.getLastName());
and it works fine however I would like to know how is best to do this, how it behaves at the object level and how high or low the performance.
Thank you ..
What you do is perfectly valid, but not very logical. Why not just drop the setEntireName() since it just combines two existing fields?
public String getEntireName() {
return firstName + " " + lastname;
}
This is valid. There is no performance difference, becasue JIT compiler optimize this code if needed (simply replace method with fields access).
Typically it is easier to eliminate the entireName property and its setter, and use the getter to perform the concatenation like so:
public String getEntireName() {
return firstName + " " + lastName;
}
This is also easier to maintain than updating entireName every time firstName or lastName is changed.
Recently I am doing a coding exercises I need to make my project , and so far I am practicing it with the code below what I want to ask is that, is this a has a relationship? am I doing the right practice? look at my code, sorry for my bad english
public class Personal {
private String firstName;
private String middleInitial;
private String lastName;
private int age;
public Personal(String firstName,String middleInitial , String lastName , int age){
setFirstName(firstName);
setMiddleInitial(middleInitial);
setLastName(lastName);
setAge(age);
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getFirstName(){
return firstName;
}
public void setMiddleInitial(String middleInitial){
this.middleInitial = middleInitial;
}
public String getMiddleInitial(){
return middleInitial;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public String getLastName(){
return lastName;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public String toString(){
return String.format("First Name: "+getFirstName()+"\nMiddle Initial: "+getMiddleInitial()+
"\nLast Name: "+getLastName()+"\nAge: "+getAge());
}
}
Contact Class
public class Contact {
private String address;
private String email;
private String contactNumber;
public Contact(String address,String contactNumber, String email){
setAddress(address);
setContactNumber(contactNumber);
setEmail(email);
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
public void setEmail(String email){
this.email = email;
}
public String getEmail(){
return email;
}
public void setContactNumber(String contactNumber){
this.contactNumber = contactNumber;
}
public String getContactNumber(){
return contactNumber;
}
public String toString(){
return String.format("Address: "+getAddress()+"\nContact Number: "+getContactNumber()+
"\nEmail Address: "+getEmail());
}
}
Employee Class
public class Employee {
private Personal personal;
private Contact contact;
public Employee(Personal personal, Contact contact){
this.personal = personal;
this.contact = contact;
}
public void setFirstName(String firstName){
this.personal.setFirstName(firstName);
}
public String toString(){
return String.format(personal.toString()+contact.toString());
}
}
And the Test class
public class TestClass {
public static void main(String[] args){
Personal personalHerp = new Personal("John","M","Doe",18);
Contact contactHerp = new Contact("88 Herp Derp St U mad New york","724-15-70","fido.com");
Employee employeeHerp = new Employee(personalHerp,contactHerp);
System.out.println(employeeHerp);
}
}
Well, since Employee doesn't extend Personal it has a Personal and a Contact.
I guess you'd rather like Employee to be a Personal and thus it should look like this:
public class Employee extends Personal {
private Contact contact;
...
}
So to summarize:
is-a means a class/object extends another class or implements an interface, i.e. A is-a B if A extends B or A implements B
has-a means that a class/object has a variable of that type, like Contact contact in your Employee class, which means Employee has-a contact.
Yes, this is a "has-a" relationship (exactly as we discussed in your other question).