设计模式之创建型(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.如果对象内部发生变化, 建造者都要修改,成本较大,适用于对象组成部分基本相同

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容