// builder pattern // some fields are mandatory., some of them are optional // hard to intisalize all the constructors to take care of all the cases // solution 1 : // so use setter/getters // limitation: need to call setters many times to finish object creation // don't really knoe when we are done creating an object // also what if we don't want to expose setters for some data fields? public class User{ private final String firstName; // required private final String lastName; // required private int age; // optinal private String phone; // optional private String address; // optional public User(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public int getAge(){ return age; } public void setAge(int age){ this.age = age; } public String getPhone(){ return phone; } public void setPhone(){ this.phone = phone; } public String getAddress(){ return address; } public void setAddress(String address){ this.address = address; } } // solution 2 : use builder pattern public class User{ private final String firstName; // required and immutable private final String lastName; private int age; private String phone; private String address; private User(UserBuilder builder){ this.firstName = builder.firstName; this.lastName = builder.lastName; this.age = builder.age; this.phone = builder.phone; this.address = builder.address; } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public int getAge(){ return age; } public String getPhone(){ return phone; } public String getAddress(){ return address; } public static class UserBuilder{ private final String firstName;// these two are required private final String lastName; private int age = 0; // default value is 0 private String phone = ""; // default value is an empty string private String address; // default value is null public UserBuilder(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; } // all the following methods are used to set values for optional fields public UserBuilder age(int age){ this.age = age; return this; } public UserBuilder phone(String phone){ this.phone = phone; return this; } public UserBuilder address(String address){ this.address = address; return this; } public User build(){ return new User(this); } } public static void main(String[] args){ User user = new User.UserBuilder("san", "zhang") .age(25); .phone("1234566"); .address("fake address"); .build(); } } // factory pattern public interface Shape{ void draw(); } public class Rectangle implements Shape{ public Rectangle(){ } @Override public void draw(){ System.out.println("rectangle draw method"); } } public class Square implements Shape{ // attributes, constructor method ... @Override public void draw(){ System.out.println("sqaure draw method"); } } public class Circle implements Shape{ // attributes , constructor method @Override public void draw(){ System.out.println(" circle draw method"); } } public class ShapeFactory{ // use getShape method to get object of type shape public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); }else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); }else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } } public class FactoryPatternDemo{ private final ShapeFactory shapeFactory = new ShapeFactory(); publiv void demo(String[] args){ // get an object of Circle and call its draw method Shape shape1 = shapeFactory.getShape("CIRCLE"); // call draw method for circle shape1.draw(); Shape shape2 = shapeFactory.getShape("RECTANGLE"); shape2.draw(); Shape shape3 = shapeFactory.getShape("SQUARE"); shape2.draw(); } } // abstract factory pattern public interface GUIFactory{ public Button createButton(); } class WinFactory implements GUIFactory{ public Button createButton(){ return new WindowsButton(); // suppose WindowsButton is a derived class of Button } } class OSXFactory implements GUIFactory{ public Button createButton(){ return new MacButton(); // suppose MacButton is a derived class of Button } } // now we hide all the complicated logic about button creatio in our // factories. others can simply call GUIFactory createButton method class Application{ private final GUIFactory factory; Application(GUIFactory f){ this.factory = f; } void run(){ // input : the GUIFactory used to create buttons Button button = factory.createButton(); button.paint(); } } main(){ // read the configuation file // if the os specified in the configuaration file is windows, then // construct a winFactory // run an application with winFactory // else // construct an osxFactory // run an application with osxFactory } // singleton // ensure a class has only one instance, and provide a global point of access to it public class Singleton{ private static final Singleton INSTANCE = new Singleton(); private Singleton(); public static Singleton getInstance(){ return INSTANCE; } }