23种设计模式归纳总结——创建型

Posted 化作孤岛的瓜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23种设计模式归纳总结——创建型相关的知识,希望对你有一定的参考价值。

目录

1.单例模式

2.工厂模式

3.Builder模式

4.原型模式


主要解决“对象的创建”问题,将创建和使用代码解耦

1.单例模式

1.饿汉式:

在类加载时进行实例的创建与初始化

public class IdGenerator  
    private AtomicLong id = new AtomicLong(0);
    private static final IdGenerator instance = new IdGenerator();
    private IdGenerator() 
    public static IdGenerator getInstance() 
        return instance;
    
    public long getId()  
        return id.incrementAndGet();
    

2.懒汉式

用到的时候再进行实例的创建与初始化

public class IdGenerator  
  private AtomicLong id = new AtomicLong(0);
  private static IdGenerator instance;
  private IdGenerator() 
  public static synchronized IdGenerator getInstance() 
    if (instance == null) 
      instance = new IdGenerator();
    
    return instance;
  
  public long getId()  
    return id.incrementAndGet();
  

3.双重检测

既支持延迟加载、又支持高并发的单例实现方式

public class IdGenerator  
  private AtomicLong id = new AtomicLong(0);
  private static IdGenerator instance;
  private IdGenerator() 
  public static IdGenerator getInstance() 
    if (instance == null) 
      synchronized(IdGenerator.class)  // 此处为类级别的锁
        if (instance == null) 
          instance = new IdGenerator();
        
      
    
    return instance;
  
  public long getId()  
    return id.incrementAndGet();
  

4.静态内部类

比双重检测更简单的方式,利用静态内部类实现,SingletonHolder 是一个静态内部类,当外部类IdGenerator被加载的时候,并不会创建SingletonHolder实例对象。只有当调用getInstance()方法时,SingletonHolder才会被加载,这个时候才会创建instance。instance的唯一性、创建过程的线程安全性,都由JVM来保证。

public class IdGenerator  
  private AtomicLong id = new AtomicLong(0);
  private IdGenerator() 

  private static class SingletonHolder
    private static final IdGenerator instance = new IdGenerator();
  
  
  public static IdGenerator getInstance() 
    return SingletonHolder.instance;
  
 
  public long getId()  
    return id.incrementAndGet();
  

5.枚举

最简单的完美方式

public enum IdGenerator 
  INSTANCE;
  private AtomicLong id = new AtomicLong(0);
 
  public long getId()  
    return id.incrementAndGet();
  

2.工厂模式

1.简单工厂

通过if else或者switch case创建同一基类的不同子类实现

//抽象类,汽车
public abstract class Car 
    public abstract void run();


//宝马
public class BMWCar extends Car 
    private String name;
    public BMWCar(String name) 
        this.name = name;
    
    @Override
    public void run() 
        System.out.println(this.name);
    


//玛莎拉蒂
public class MaseratiCar extends Car 
    private String name;
    public MaseratiCar(String name) 
        this.name = name;
    
    @Override
    public void run() 
        System.out.println(this.name);
    


//简单工厂
public class CarFactory 
    public static Car createCar(String brand) 
        Car car = null;
        switch (brand) 
            case "maserati": // 玛莎拉蒂
                car = new MaseratiCar(brand);
                break;
            case "bmw": // 宝马
                car = new BMWCar(brand);
                break;
        
        return car;
    

2.工厂方法

如果每一个子类实例创建过程复杂,讲创建过程抽象为一个工厂,将复杂逻辑写在创建工厂类里,并通过聚合(工厂的工厂)来统一处理这些工厂类的创建。

当对象的创建逻辑比较复杂,不只是简单的new一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。

//汽车
public static abstract class Car 
    public abstract void run();


//宝马
public static class BMWCar extends Car 
    private String name;
    public BMWCar(String name) 
        this.name = name;
    
    @Override
    public void run() 
        System.out.println(this.name);
    


//汽车工厂
public interface ICarFactory 
    Car createCar(String name);


//宝马汽车工厂
public static class BWCarFactory implements ICarFactory
    @Override
    public Car createCar(String name) 
        //做一些专属于宝马的复杂事情
        return new BMWCar(name);
    


public static class CarFactoryMap  //工厂的工厂
    private static final Map<String, ICarFactory> cachedFactories = new HashMap<>();

    static 
        cachedFactories.put("bw", new BWCarFactory());
    

    public static ICarFactory getParserFactory(String type) 
        if (type == null || type.isEmpty()) 
                return null;
        
        ICarFactory parserFactory = cachedFactories.get(type.toLowerCase());
        return parserFactory;
    


public static void main(String[] args) 
    String brand = "bw";
    ICarFactory carFactory = CarFactoryMap.getParserFactory(brand);
    Car car = carFactory.createCar(brand);
    car.run();

3.抽象工厂

可以把它理解成创建工厂的工厂

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

//电脑产品接口
public interface IComputerProduct 
    void start();

    void shutdown();


//A电脑
public class AComputer implements IComputerProduct 
    @Override
    public void start() 
        System.out.println("开启A电脑");
    

    @Override
    public void shutdown() 
        System.out.println("关闭A电脑");
    


//电视机产品接口
public interface ITVProduct 
    void start();

    void shutdown();


//A电视
public class ATV implements ITVProduct 
    @Override
    public void start() 
        System.out.println("开启A电视");
    

    @Override
    public void shutdown() 
        System.out.println("关闭A电视");
    


//抽象产品工厂
public interface IProductFactory 
    //生产电脑
    IComputerProduct iComputerProduct();

    //生产电视
    ITVProduct itvProduct();


public class AFactory implements IProductFactory 
    @Override
    public IComputerProduct iComputerProduct() 
        return new AComputer();
    

    @Override
    public ITVProduct itvProduct() 
        return new ATV();
    

 

3.Builder模式

解决问题:1.某些参数必须要填,或者存在其他约束关系,set和get无法解决 2.防止构造方法膨胀 3.set方法不适合暴露

可以在build方法中做集中的参数校验,防止出错。

public class ResourcePoolConfig 
  private String name;
  private int maxTotal;

  private ResourcePoolConfig(Builder builder) 
    this.name = builder.name;
    this.maxTotal = builder.maxTotal;
  
  //...省略getter方法...

  //我们将Builder类设计成了ResourcePoolConfig的内部类。
  //我们也可以将Builder类设计成独立的非内部类ResourcePoolConfigBuilder。
  public static class Builder 
    private static final int DEFAULT_MAX_TOTAL = 8;

    private String name;
    private int maxTotal = DEFAULT_MAX_TOTAL;

    public ResourcePoolConfig build() 
      // 校验逻辑放到这里来做,包括必填项校验、依赖关系校验、约束条件校验等
      if (StringUtils.isBlank(name)) 
        throw new IllegalArgumentException("...");
      
      if (maxTotal < DEFAULT_MAX_TOTAL) 
        throw new IllegalArgumentException("...");
      
      return new ResourcePoolConfig(this);
    

    public Builder setName(String name) 
      if (StringUtils.isBlank(name)) 
        throw new IllegalArgumentException("...");
      
      this.name = name;
      return this;
    

    public Builder setMaxTotal(int maxTotal) 
      if (maxTotal <= 0) 
        throw new IllegalArgumentException("...");
      
      this.maxTotal = maxTotal;
      return this;
    
  

4.原型模式

如果对象的创建成本比较大(对象中的数据需要经过复杂的计算才能得到(比如排序、计算哈希值),或者需要从RPC、网络、数据库、文件系统等非常慢速的IO中读取),而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(Prototype Design Pattern),简称原型模式。

浅拷贝和深拷贝的区别在于,浅拷贝只会复制图中的索引(散列表),不会复制数据(SearchWord对象)本身。相反,深拷贝不仅仅会复制索引,还会复制数据本身。

// 定义Food类
class Food
    String food;
    // get set ...
    public Food(String food) 
            this.food = food;
    


// 定义Student类
class Student implements Cloneable // Cloneable接口

	@Override
	public Object clone() throws CloneNotSupportedException  // 提升访问权限
        Student student = (Student) super.clone();
        //针对成员变量进行拷贝
        student.name = new String(name);
        student.food = new Food(food.getFood());
        return student;
	

    private Food food;
    private String name;
    int age;

    public Student() 
    

    public Student(String name, int age, Food food) 
            this.name = name;
            this.age = age;
            this.food = food;
    
    //get set..


//测试
Food food  = new Food("apple");
System.out.println(food); // JavaPackage_1.Food@6d311334

//Java深拷贝,对内层的对象也进行拷贝。
Student student1 = new Student("stu", 29,food);
// 通过student1克隆student2,不通过new对象的形式创建
Student student2 = (Student) student1.clone(); 

System.out.println(student1); // JavaPackage_1.Student@3d075dc0
System.out.println(student2); // JavaPackage_1.Student@214c265e
System.out.println(student1==student2); // false,student1和student2指向的是不同地址

System.out.println(student1.getFood()); // JavaPackage_1.Food@6d311334
System.out.println(student2.getFood()); // JavaPackage_1.Food@448139f0
System.out.println(student1.getFood()==student2.getFood()); // false,student1.food和student2.food指向不同地址

food.setFood("orange");
System.out.println(student1.getFood().getFood()); // orange
System.out.println(student2.getFood().getFood()); // apple

以上是关于23种设计模式归纳总结——创建型的主要内容,如果未能解决你的问题,请参考以下文章

23种设计模式归纳总结——创建型

23种设计模式归纳总结——创建型

23种设计模式归纳总结——行为型

23种设计模式归纳总结——行为型

23种设计模式归纳总结——行为型

23种设计模式