设计模式系列 - 创建型模式
单例模式

懒汉式,线程不安全。
除非是单线程程序,否则不推荐使用。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}饿汉式,线程安全
当程序总是使用这个类的实例时,或者在资源和时间方面创建实例的成本不太大时,可以使用它。
可能导致资源浪费。因为类的实例总是被创建的,不管它是否必需。在创建实例时也会浪费CPU时间。
无法处理异常。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}静态块,线程安全
对象是在静态块中创建的,这样我们就可以访问它的创建,比如异常处理。同样地,对象也是在类加载时创建的。
当在创建具有紧急初始化的对象时可能出现异常时,可以使用它。可能导致资源浪费。因为类的实例总是被创建的,不管它是否必需。
public class Singleton
{
// public instance
public static Singleton instance;
private Singleton()
{
// private constructor
}
{
// static block to initialize instance
instance = new Singleton();
}
}同步方式,线程安全
会导致性能下降
public class Singleton
{
// private instance, so that it can be
// accessed by only by getInstance() method
private static Singleton instance;
private Singleton()
{
// private constructor
}
//synchronized method to control simultaneous access
synchronized public static Singleton getInstance()
{
if (instance == null)
{
// if instance is null, initialize
instance = new Singleton();
}
return instance;
}
}双检方式,线程安全
克服了同步代码的开销问题。延迟初始化,可以用于高性能的多线程应用。
public class Singleton
{
// private instance, so that it can be
// accessed by only by getInstance() method
private static Singleton instance;
private Singleton()
{
// private constructor
}
public static Singleton getInstance()
{
if (instance == null)
{
//synchronized block to remove overhead
synchronized (Singleton.class)
{
if(instance==null)
{
// if instance is null, initialize
instance = new Singleton();
}
}
}
return instance;
}
}内部静态类方案,优方案
加载单例类时,不会加载内部类,因此在加载类时不会创建对象。只有在调用getInstance()方法时才创建内部类。它是懒惰的初始化。
这是最广泛使用的方法,因为它不使用同步,性能更好。
public class Singleton
{
private Singleton()
{
// private constructor
}
// Inner class to provide instance of class
private static class BillPughSingleton
{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance()
{
return BillPughSingleton.INSTANCE;
}
}枚举,优方案
自动支持序列化机制,绝对防止多次实例化。这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}工厂方法

是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
//定义车类
public enum CarType {
SMALL, SEDAN, LUXURY
}
//车的基类
public abstract class Car {
public Car(CarType model) {
this.model = model;
arrangeParts();
}
private void arrangeParts() {
// Do one time processing here
}
// Do subclass level processing in this method
protected abstract void construct();
private CarType model = null;
public CarType getModel() {
return model;
}
public void setModel(CarType model) {
this.model = model;
}
}
//豪华车
public class LuxuryCar extends Car {
LuxuryCar() {
super(CarType.LUXURY);
construct();
}
@Override
protected void construct() {
System.out.println("Building luxury car");
// add accessories
}
}
public class SmallCar extends Car {
SmallCar() {
super(CarType.SMALL);
construct();
}
@Override
protected void construct() {
System.out.println("Building small car");
// add accessories
}
}
public class SedanCar extends Car {
SedanCar() {
super(CarType.SEDAN);
construct();
}
@Override
protected void construct() {
System.out.println("Building sedan car");
// add accessories
}
}
public class CarFactory {
public static Car buildCar(CarType model) {
Car car = null;
switch (model) {
case SMALL:
car = new SmallCar();
break;
case SEDAN:
car = new SedanCar();
break;
case LUXURY:
car = new LuxuryCar();
break;
default:
// throw some exception
break;
}
return car;
}
}
public class TestFactoryPattern {
public static void main(String[] args) {
System.out.println(CarFactory.buildCar(CarType.SMALL));
System.out.println(CarFactory.buildCar(CarType.SEDAN));
System.out.println(CarFactory.buildCar(CarType.LUXURY));
}
}抽象工厂


围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
我们重用上一节的CarType
public abstract class Car {
public Car(CarType model, Location location){
this.model = model;
this.location = location;
}
protected abstract void construct();
private CarType model = null;
private Location location = null;
//getters and setters
@Override
public String toString() {
return "Model- "+model + " built in "+location;
}
}
public enum Location {
DEFAULT, USA, ASIA
}
public class LuxuryCar extends Car
{
public LuxuryCar(Location location)
{
super(CarType.LUXURY, location);
construct();
}
@Override
protected void construct() {
System.out.println("Building luxury car");
//add accessories
}
}
public class AsiaCarFactory
{
public static Car buildCar(CarType model)
{
Car car = null;
switch (model)
{
case SMALL:
car = new SmallCar(Location.ASIA);
break;
case SEDAN:
car = new SedanCar(Location.ASIA);
break;
case LUXURY:
car = new LuxuryCar(Location.ASIA);
break;
default:
//throw some exception
break;
}
return car;
}
}
public class DefaultCarFactory
{
public static Car buildCar(CarType model)
{
Car car = null;
switch (model)
{
case SMALL:
car = new SmallCar(Location.DEFAULT);
break;
case SEDAN:
car = new SedanCar(Location.DEFAULT);
break;
case LUXURY:
car = new LuxuryCar(Location.DEFAULT);
break;
default:
//throw some exception
break;
}
return car;
}
}
public class USACarFactory
{
public static Car buildCar(CarType model)
{
Car car = null;
switch (model)
{
case SMALL:
car = new SmallCar(Location.USA);
break;
case SEDAN:
car = new SedanCar(Location.USA);
break;
case LUXURY:
car = new LuxuryCar(Location.USA);
break;
default:
//throw some exception
break;
}
return car;
}
}
public class CarFactory
{
private CarFactory() {
//Prevent instantiation
}
public static Car buildCar(CarType type,Location location)
{
Car car = null;
//Use location specific car factory
switch(location)
{
case USA:
car = USACarFactory.buildCar(type);
break;
case ASIA:
car = AsiaCarFactory.buildCar(type);
break;
default:
car = DefaultCarFactory.buildCar(type);
}
return car;
}
}
public class TestFactoryPattern
{
public static void main(String[] args)
{
System.out.println(CarFactory.buildCar(CarType.SMALL,Location.USA));
System.out.println(CarFactory.buildCar(CarType.SEDAN,Location.USA));
System.out.println(CarFactory.buildCar(CarType.LUXURY,Location.ASIA));
}
}这两个工厂模式的代码还有很多switch,仅仅是演示而已
建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
interface HousePlan
{
public void setBasement(String basement);
public void setStructure(String structure);
public void setRoof(String roof);
public void setInterior(String interior);
}
class House implements HousePlan
{
private String basement;
private String structure;
private String roof;
private String interior;
public void setBasement(String basement)
{
this.basement = basement;
}
public void setStructure(String structure)
{
this.structure = structure;
}
public void setRoof(String roof)
{
this.roof = roof;
}
public void setInterior(String interior)
{
this.interior = interior;
}
}
interface HouseBuilder
{
public void buildBasement();
public void buildStructure();
public void bulidRoof();
public void buildInterior();
public House getHouse();
}
class IglooHouseBuilder implements HouseBuilder
{
private House house;
public IglooHouseBuilder()
{
this.house = new House();
}
public void buildBasement()
{
house.setBasement("Ice Bars");
}
public void buildStructure()
{
house.setStructure("Ice Blocks");
}
public void buildInterior()
{
house.setInterior("Ice Carvings");
}
public void bulidRoof()
{
house.setRoof("Ice Dome");
}
public House getHouse()
{
return this.house;
}
}
class TipiHouseBuilder implements HouseBuilder
{
private House house;
public TipiHouseBuilder()
{
this.house = new House();
}
public void buildBasement()
{
house.setBasement("Wooden Poles");
}
public void buildStructure()
{
house.setStructure("Wood and Ice");
}
public void buildInterior()
{
house.setInterior("Fire Wood");
}
public void bulidRoof()
{
house.setRoof("Wood, caribou and seal skins");
}
public House getHouse()
{
return this.house;
}
}
class CivilEngineer
{
private HouseBuilder houseBuilder;
public CivilEngineer(HouseBuilder houseBuilder)
{
this.houseBuilder = houseBuilder;
}
public House getHouse()
{
return this.houseBuilder.getHouse();
}
public void constructHouse()
{
this.houseBuilder.buildBasement();
this.houseBuilder.buildStructure();
this.houseBuilder.bulidRoof();
this.houseBuilder.buildInterior();
}
}
class Builder
{
public static void main(String[] args)
{
HouseBuilder iglooBuilder = new IglooHouseBuilder();
CivilEngineer engineer = new CivilEngineer(iglooBuilder);
engineer.constructHouse();
House house = engineer.getHouse();
System.out.println("Builder constructed: "+ house);
}
}以上是做分部建造,还可以避免new product的过多参数,比如:
public User (String firstName, String lastName, int age, String phone){ ... }
public User (String firstName, String lastName, String phone, String address){ ... }
public User (String firstName, String lastName, int age){ ... }
public User (String firstName, String lastName){ ... }如果再多十几个属性怎么办?
public class User
{
//All final attributes
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//All getter, and NO setter to provde immutability
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;
}
@Override
public String toString() {
return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address;
}
public static class UserBuilder
{
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
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;
}
//Return the finally consrcuted User object
public User build() {
User user = new User(this);
validateUserObject(user);
return user;
}
private void validateUserObject(User user) {
//Do some basic validations to check
//if user object does not break any assumption of system
}
}
}
public static void main(String[] args) {
User user1 = new User.UserBuilder("Lokesh", "Gupta")
.age(30)
.phone("1234567")
.address("Fake address 1234")
.build();
System.out.println(user1);
User user2 = new User.UserBuilder("Jack", "Reacher")
.age(40)
.phone("5655")
//no address
.build();
System.out.println(user2);
User user3 = new User.UserBuilder("Super", "Man")
//No age
//No phone
//no address
.build();
System.out.println(user3);
}原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。原型设计模式用于应用程序需要创建一个类的多个实例的场景中,这些实例几乎具有相同的状态或差别非常小。
在这个设计模式中,实际对象的一个实例(即prototype)是在启动时创建的,然后每当需要新实例时,就克隆这个原型以拥有另一个实例。这种模式的主要优点是具有最小的实例创建过程
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
public interface PrototypeCapable extends Cloneable
{
public PrototypeCapable clone() throws CloneNotSupportedException;
}
public class Movie implements PrototypeCapable
{
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Movie clone() throws CloneNotSupportedException {
System.out.println("Cloning Movie object..");
return (Movie) super.clone();
}
@Override
public String toString() {
return "Movie";
}
}
public class Album implements PrototypeCapable
{
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Album clone() throws CloneNotSupportedException {
System.out.println("Cloning Album object..");
return (Album) super.clone();
}
@Override
public String toString() {
return "Album";
}
}
public class Show implements PrototypeCapable
{
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Show clone() throws CloneNotSupportedException {
System.out.println("Cloning Show object..");
return (Show) super.clone();
}
@Override
public String toString() {
return "Show";
}
}
public class PrototypeCache
{
public static class ModelType
{
public static final String MOVIE = "movie";
public static final String ALBUM = "album";
public static final String SHOW = "show";
}
private static java.util.Map<String , PrototypeCapable> prototypes = new java.util.HashMap<String , PrototypeCapable>();
static
{
prototypes.put(ModelType.MOVIE, new Movie());
prototypes.put(ModelType.ALBUM, new Album());
prototypes.put(ModelType.SHOW, new Show());
}
public static PrototypeCapable getInstance(final String s) throws CloneNotSupportedException {
return ((PrototypeCapable) prototypes.get(s)).clone();
}
}
TestPrototypePattern
public class TestPrototypePattern
{
public static void main(String[] args)
{
try
{
String moviePrototype = PrototypeCache.getInstance(ModelType.MOVIE).toString();
System.out.println(moviePrototype);
String albumPrototype = PrototypeCache.getInstance(ModelType.ALBUM).toString();
System.out.println(albumPrototype);
String showPrototype = PrototypeCache.getInstance(ModelType.SHOW).toString();
System.out.println(showPrototype);
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
}
}Singleton