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

单例模式

懒汉式,线程不安全。

除非是单线程程序,否则不推荐使用。

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

原文地址:https://www.cnblogs.com/starcrm/p/12572620.html

时间: 03-26

设计模式系列 - 创建型模式的相关文章

设计模式之创建型模式(上)

没有总结的学习不算学习,这一个月的学习可谓收获多多啊,接下来与大家分享一下. 一.设计模式的分类 总体来说设计模式分为三大类: 1.创建型模式,共五种. 2.结构型模式,共七种. 3.行为型模式,共十一种. 首先研究创建型模式 二. 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独 立于如何创建.组合和表示它的那些对象. 三. 为什么需要创建型模式 所有的创建型模式都有两个永恒的主旋律: 第一,它们都将系统使用哪些具体类的信息封装起来: 第二,它们隐藏了这些类的实例

【设计模式】创建型模式之抽象工厂Abstract Factory

抽象工厂Abstract Factory是一种创建型设计模式,目的在于提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.抽象工厂的类图如下,客户仅与抽象类定义的定义的接口交互,而不使用特定的具体类的接口.一个系统包含多种产品时,AbstractFactory声明创建各种抽象产品对象的操作接口,这些接口是直接暴露给Client的,而具体产品对象的创建则延迟到子类ConcreteFactory,Client面对的产品类是AbstractProduct,无需关系具体产品类是什么.在运

设计模式之创建型模式—— 1.5 原型模式

<?php /**  * 1.5 原型模式  *  解决的问题:  *  某些结构复杂的对象的创建工作,由于需  *  求的变化,这些对象经常面临着剧烈的变  *  化,但是它们却有用比较稳定一种的接口.  *  解决的方案:  *   用原型实例指定创建对象的种类,并且通  *   过拷贝这些原型创建新的对象.  *  该模式无需任何角色:  *   因为在PHP中,在每个声明的类中已经默认  *   包含了克隆函数,所以无需单独在建立一个  *   抽象类来实现克隆操作了.  *  优点:

设计模式之创建型模式—— 1.1 简单工厂模式

<?php                  /** * 1.1 简单工厂模式 * * 解决的问题: *  如何解决多个类实例化对象的问题. *  注意:因为是简单工厂模式,所以要实例 *    化的类不能太多,否则请使用1.2节 *    的工厂方法模式. * * 解决方案: *  建立一个工厂(即一个工厂类),通过参数的 *  传递动态决定应该创建哪一个产品类(这些 *  产品类继承自一个父类或接口)的实例. *  *  * 该模式中包含三种角色: *  注:这里的角色指的就是类! *  1

设计模式之创建型模式—— 1.2 工厂方法模式

<?php /**  * 1.2 工厂方法模式  * 解决的问题:  *  如何解决多个类实例化对象的问题.  *   * 解决的方案:  *  定义一个用于创建对象的接口,让子类决定  *  实例化哪一个类.工厂方法使一个类的实例  *  化延迟到其子类.  *   * 该模式包含四种角色:  *  1. 抽象产品角色(一个)  *  职责:它是具体工厂角色所创建的对象  *    的父类.负责描述所有实例所共  *    有的公共接口.  *  2. 具体产品角色  *  职责:它是具体工厂

设计模式之创建型模式—— 1.3 抽象工厂模式

<?php /**  * 1.3 抽象工厂模式  * 解决的问题:  *  如何解决多个类实例化对象的问题.  * 解决的方案:  *  提供一个创建一系列相关或相互依赖对象的  *    接口,而无需指定它们具体的类.  * 该模式包含四种角色:  *  1. 抽象产品角色(两个或多个)  *  职责:同工厂方法模式  *    2. 具体产品角色  *    职责:同工厂方法模式  *      3. 抽象工厂角色  *    职责:同工厂方法模式  *      4. 具体工厂角色  * 

设计模式之创建型模式—— 1.4 单例模式

<?php /**  * 1.4 单例模式  *  解决的问题:  *   如何确保一个特殊类的实例是独一无二的  *   ,也就是说这个实例是它所属类的唯一一  *   个实例对象,并且很容易的对它进行存取?  *  解决的方案:  *   保证一个类仅有一个实例,并提供一个访  *   问它的全局访问点.  *  该模式包含一种角色:  *   1. 单例角色  *  优点:  *   1. 始终保持唯一的一个实例.  *   2. 可对此唯一实例进行访问控制.  *  缺点:  *   1

设计模式之创建型模式—— 1.6 建造者模式

<?php /**  * 1.6 建造者模式  * 定义:  *  将一个复杂对象的构建与它的表示分离  *  ,使得同样的构建过程可以创建不同的  *  表示.  * 此模式包含三种角色:  *  1. 抽象建造者角色  *  职责:  *  用于指定规则和流程  *  2. 具体建造者角色  *  职责:  *  具体的建造过程  *  3. 指挥者角色  *  职责:  *  用于指挥建造过程  *      4. 具体产品角色  *  * 优点:  *  1. 封装性  *  2. 建造

Java的23种设计模式详解整理之创建型模式

最近重新阅读"四巨头"的设计模式. 对一些设计模式有了更多的理解. 原著中的例子是C++写的,不好理解. 这里我换成了Java, 代码示例仅供参考,没有具体实现. 介于个人水平有限,如有纰漏,请指正.有问题的朋友可以私信我或者发我邮箱(请到我主页查看),我看到就会回复. 希望和大家一起进步. 工作中有时候最困难的不是怎么去实现一个功能,而是怎么去设计一个功能.我常常会因为频繁改动需求大费脑筋.之后我在思考如何将一个功能在设计之初就做好扩展的准备,防止需求变动导致大面积的修改.code之

C#设计模式-创建型模式(转)

一.简单工厂模式 简单工厂模式Simple Factory,又称静态工厂方法模式.它是类的创建模式.是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一个特殊实现. 优点: u 模式的核心是工厂类,该类中含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅负责"消费"产品. u 简单工厂模式实现了对责任的分割. 缺点: u 当产品类有复杂的多层次等级结构时,工厂类只有它自己.以不变应万变. u 模式中工厂类集中了所