110.【十万字带你深入学习23种设计模式】(五)

简介: 110.【十万字带你深入学习23种设计模式】

(二)、创建者模式(5种)

创建者模式的主要关注点: “怎么创建对象”,它的主要特点是:“将对象的创建和使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。

1.单列模式

单列模式 是Java中最简单的设计模式之一。这种类型的设计属于创建型模式,他提供了一种创建对象的最佳方式。

这种模式会涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其他唯一的方式,可以直接访问,不需要实列化该类的对象

(1).单列模式的结构

单列模式饿主要有以下角色:

  1. 单列模式。只能创建一个实列的类
  2. 访问类。使用单列类
(2).单列模式的实现

单列设计模式分类两种:

  1. 饿汉式: 类加载就会导致该单实列对象被创建(加载的时候就创建)
  2. 懒汉式: 类加载不会导致该单列对象被创建,而是首次使用该对象时才会创建
(3).饿汉式的两种方式
  1. 饿汉式-方式一 (静态变量方式)

单列模式

package com.jsxs.pattern.singletion.demo1;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:11
 * @PackageName:com.jsxs.pattern.singletion.demo1
 * @ClassName: Singletion
 * @Description: TODO  静态成员变量
 * @Version 1.0
 */
public class Singletion {
    // 1.私有构造方法:  外界不能创建这个对象也就是->new
    private Singletion() {
    }
    //2.在本类中创建该类的对象:  private->外界不能直接访问。 static->设置为静态的变量,目的是为了让静态方法获取。
    private static Singletion singletion=new Singletion();
    //3.提供一个公共的访问方式,让外界获取该对象
    public static Singletion getInstance(){
        return singletion;
    }
}

访问类

package com.jsxs.pattern.singletion.demo1;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:21
 * @PackageName:com.jsxs.pattern.singletion.demo1
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        //1.创建Singletion类的对象
        Singletion instance = Singletion.getInstance();
        Singletion instance1 = Singletion.getInstance();
        // 2.判断创建得到这两个对象是否是一个对象
        System.out.println(instance==instance1);  // == 判断的时地址
    }
}

  1. 饿汉式-方式二 (静态代码块)
package com.jsxs.pattern.singletion.demo2;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:30
 * @PackageName:com.jsxs.pattern.singletion.demo2
 * @ClassName: Singleton
 * @Description: TODO  饿汉式2- 静态代码块----  静态变量和静态代码块谁先声明谁先执行。
 * @Version 1.0
 */
public class Singleton {
    // 1.私有构造方法
    private Singleton(){}
    //2.声明Singleton类型的变量
    private static  Singleton instance; // 并未初始化
    //3.静态代码块中进行赋值
    static {
        instance=new Singleton();
    }
    //4.对外提供该类对象的方法
    public static Singleton getInstance(){
        return instance;
    }
}
package com.jsxs.pattern.singletion.demo2;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:34
 * @PackageName:com.jsxs.pattern.singletion.demo2
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance==instance1);
    }
}

说明: 该方式在成员位置声明Singleton类型的静态变量,而对象的创建时在静态代码块中,也是对着类的加载而创建。所以和饿汉式的方式1基本一样,当然该方式也存在内存浪费的问题



(4).懒汉式的七种方式
  1. 饿汉式-方式1 (静态方式-线程不安全)
package com.jsxs.pattern.singletion.demo3;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:43
 * @PackageName:com.jsxs.pattern.singletion.demo3
 * @ClassName: Singleton
 * @Description: TODO  懒汉式-1
 * @Version 1.0
 */
public class Singleton {
    // 1.私有构造方法
    private Singleton(){}
    // 2.声明Singleton类型的变量---*******并没有赋值的操作
    private static Singleton instace;
    //3.对外提供访问方式
    public static Singleton getInstance(){
        if (instace==null){  //1.如果以前没有创建对象,那么就创建一个对象。如果创建过,那么就直接返回我们第一次创建的对象。
            instace=new Singleton();
        }
        return instace;
    }
}
package com.jsxs.pattern.singletion.demo3;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:50
 * @PackageName:com.jsxs.pattern.singletion.demo3
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        System.out.println( Singleton.getInstance().hashCode());
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance1.hashCode());
    }
}

我们发现在单线程的情况下: 哈希值是一样的也就是对象是一样的

问题: 多线程的情况下: 会出现哈希值的不一致->对象不一致。

package com.jsxs.pattern.singletion.demo3;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:43
 * @PackageName:com.jsxs.pattern.singletion.demo3
 * @ClassName: Singleton
 * @Description: TODO  懒汉式-1
 * @Version 1.0
 */
public class Singleton {
    // 1.私有构造方法
    private Singleton(){}
    // 2.声明Singleton类型的变量---*******并没有赋值的操作
    private static Singleton instace;
    //3.对外提供访问方式
    public static Singleton getInstance(){
        if (instace==null){  //1.如果以前没有创建对象,那么就创建一个对象。如果创建过,那么就直接返回我们第一次创建的对象。
            try {
                Thread.sleep(2000);   //等待2秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instace=new Singleton();
        }
        return instace;
    }
}
package com.jsxs.pattern.singletion.demo3;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:50
 * @PackageName:com.jsxs.pattern.singletion.demo3
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        new Thread(()->{
            System.out.println( Singleton.getInstance().hashCode());
        }).start();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance1.hashCode());
    }
}

  1. 懒汉式-2 (线程安全)

这里我们在创建对象的时候只是添加了 同步锁Synchronized

package com.jsxs.pattern.singletion.demo3;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:43
 * @PackageName:com.jsxs.pattern.singletion.demo3
 * @ClassName: Singleton
 * @Description: TODO  懒汉式-2  (线程安全)
 * @Version 1.0
 */
public class Singleton {
    // 1.私有构造方法
    private Singleton(){}
    // 2.声明Singleton类型的变量---*******并没有赋值的操作
    private static Singleton instace;
    //3.对外提供访问方式
    public static synchronized Singleton getInstance(){  // -**********添加了同步锁: "没有执行完毕,不释放资源"
        if (instace==null){  //1.如果以前没有创建对象,那么就创建一个对象。如果创建过,那么就直接返回我们第一次创建的对象。
            try {
                Thread.sleep(2000);   //等待2秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instace=new Singleton();
        }
        return instace;
    }
}
package com.jsxs.pattern.singletion.demo3;
/**
 * @Author Jsxs
 * @Date 2023/4/16 14:50
 * @PackageName:com.jsxs.pattern.singletion.demo3
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        new Thread(()->{
            System.out.println( Singleton.getInstance().hashCode());
        }).start();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance1.hashCode());
    }
}

说明: 该方式实现了懒加载的效果,同时又解决了线程安全问题。但是在GetInstance()方法上添加Synchronized关键字,导致该方法的执行效率特别低。从上面的代码我们可以看出,其实就是在初始化inatance的时候才会出现线程安全问题,一旦初始化完成就不存在了。

相关文章
|
6月前
|
设计模式 监控 安全
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
101 0
|
5月前
|
设计模式 存储 算法
设计模式学习心得之五种创建者模式(2)
设计模式学习心得之五种创建者模式(2)
45 2
|
5月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
40 2
|
5月前
|
设计模式 安全 Java
设计模式学习心得之五种创建者模式(1)
设计模式学习心得之五种创建者模式(1)
38 0
|
5月前
|
设计模式 数据可视化 程序员
设计模式学习心得之前置知识 UML图看法与六大原则(上)
设计模式学习心得之前置知识 UML图看法与六大原则(上)
44 0
|
6月前
|
设计模式 安全 Java
【JAVA学习之路 | 基础篇】单例设计模式
【JAVA学习之路 | 基础篇】单例设计模式
|
6月前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
6月前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
6月前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
6月前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式

热门文章

最新文章

  • 1
    C++一分钟之-设计模式:工厂模式与抽象工厂
    42
  • 2
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    46
  • 3
    C++一分钟之-C++中的设计模式:单例模式
    54
  • 4
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    38
  • 5
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    62
  • 6
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    57
  • 7
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    41
  • 8
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    50
  • 9
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    106
  • 10
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    78