设计模式之创建型(5)

创建型模式 主要是用于产生类实例,也就是new 对象
共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

一.单例模式

1.一句话描述

  • 确保一个类只会生成一个实例,并提供一个全局访问点

2.实现方式

单例模式可以细分懒汉模式饿汉模式两种模式:

(1).懒汉模式

public class Singleton{

    //使用volatile关键字防止重排序,因为 new 实例是一个非原子操作
    private volatile static Singleton singleton; 
    //私有构造函数
    private Singleton(){}

    public static Singleton getSingleton(){
        if(singleton==null){
            //只对实例化代码块加锁,提升性能
            synchronized (Singleton.class){   
                if (singleton == null) { //双重检查
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

在JDK1.4及更早版本的JAVA中,volatile关键字的实现会导致双重检查加锁的失效

(2).饿汉模式

public class Singleton{
    private static Singleton singleton = new Singleton(); 
    //私有构造函数
    private Singleton(){}

    public static Singleton getSingleton(){
        return singleton;
    }
}

利用JVM在加载完这个类时,马上实例化唯一的实例,保证线程安全

实战场景:

  • Spring Bean 管理默认就是一种单例模式

二、工厂模式

1.一句话描述

  • 定义一个创建对象的接口,由子类实例化具体对象,一个具体子类对应一种产品类对象

2. 实现方式

(1) 简单工厂

class Juice{ }
class AppleJuice extends Juice{}
class PearJuice extends Juice{}

class JuiceStore{  
    public static Juice createJuice(String fruit) {  //简单工厂方法, 新增产品类,需要修改工厂方法,不符合开闭原则
        if ("apple".equals(fruit)) {
            return new AppleJuice();
        } else if ("pear".equals(fruit)) {
            return new PearJuice();
        } else {
            return null;
        }
    }
}

(2)工厂 方法

class Juice{ }   //抽象产品类
class AppleJuice extends Juice{} //具体产品类
class PearJuice extends Juice{}

abstract class JuiceStore{   //抽象工厂类
    public abstract Juice createJuice();
}

class AppleStore extends JuiceStore { //具体产品类

    @Override
    public Juice createJuice() {
        return new AppleJuice();
    }
}
class PearStore extends JuiceStore{//具体产品类

    @Override
    public Juice createJuice() {
        return new PearJuice();
    }
}

3. 类图

image.png

4.总结

1.工厂模式相比简单工厂,加入了"开闭原则", 创建工厂和 产品实现解耦
2.每增加一个产品实现类,要增加一个工厂创建类
3.工厂模式 是抽象工厂的一个比较常见的情况

三、抽象工厂模式

1.一句话描述

  • 提供一个负责创建一组产品的接口,接口内每个方法由子类负责创建一个具体产品

2.类图/实例

class Juice{}
class AppleJuice extends Juice{}
class IceAppleJuice extends AppleJuice { }
class CommonAppleJuice extends AppleJuice{}

class PearJuice extends Juice{}

class IcePearJuice extends PearJuice { }
class CommonPearJuice extends PearJuice{}
//超级工厂,包含两个工厂方法
abstract class Store{
    public abstract Juice createAppleJuice();
    public abstract Juice createPearJuice();
}

class OneStore extends Store {
    @Override
    public Juice createAppleJuice() {
        return new IceAppleJuice();
    }
    @Override
    public Juice createPearJuice() {
        return new IcePearJuice();
    }
}
class TwoStore extends Store{

    @Override
    public Juice createAppleJuice() {
        return new CommonAppleJuice();
    }
    @Override
    public Juice createPearJuice() {
        return new CommonPearJuice();
    }
}

3.实战案例

4.总结

1.在一个工厂里聚合多个同类产品(同类产品的不同系列)
2.简化产品族的交换
3.产品族要扩展,需要修改所有工厂类,不易扩展产品族

四、原型模式

1. 一句话描述

  • 利用原对象快速复制一个对象

2.实战案例

  • Object 对象clone方法,本地方法默认实现浅克隆
  • Spring中原型bean的创建,就是原型模式的应用

3.实现方式

分为浅克隆深克隆

  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原
    有属性所指向的对象的内存地址, 也就是引用类型指向的是同一个
// 实现Cloneable接口
public class InstanceClone implements Cloneable{
    // ...省略
    @Override
    protected Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // TODO Auto-generated method stub
        return clone;
    }
}

  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
//通过对象的序列化实现
    public Object deepClone() {
        //创建流
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis =null;
        ObjectInputStream ois = null;
        
        try {
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);//当前的对象以流的方式输出
            
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            InstanceClone deepClone = (InstanceClone )ois.readObject();
            
            return deepClone ;
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        }finally {
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
            }
        }
        
    }

也可以通过重写clone方法来实现深拷贝,但不推荐

4.总结

1.原型模式可以快速创建复杂对象,同时提高效率
2.需要在类中实现克隆方法, 违背了OCP开闭原则

五、建造者模式

1. 一句话描述

  • 对复杂对象的组件创建以及组合进行了抽取和拆分

2.类图

image.png

3. 实战场景

  • JDK中 StringBuilder
  • MybatisPlus中的QueryWrapper对象的构建
  • Mybatis中用到的建造者模式:SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder等

4.总结

1.将复杂对象的创建步骤分解在不同的方法中,使得创建过程更加清晰,对象创建更加灵活
2.使用方不必知道对象内部组成细节,对象本身和对象创建过程解耦
3.如果对象内部发生变化, 建造者都要修改,成本较大,适用于对象组成部分基本相同

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容