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天前
|
设计模式 存储 Java
认真学习设计模式之观察者模式(Observer Pattern)
认真学习设计模式之观察者模式(Observer Pattern)
35 0
|
6月前
|
设计模式 缓存 Java
认真学习设计模式之建造者模式(Builder Pattern)
认真学习设计模式之建造者模式(Builder Pattern)
63 1
|
6天前
|
设计模式 监控 安全
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
62 0
|
4天前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
6天前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
6天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
6天前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
6天前
|
设计模式 存储 Java
认真学习设计模式之命令模式(Command Pattern)
认真学习设计模式之命令模式(Command Pattern)
87 0
|
6天前
|
设计模式 安全 Java
多线程设计模式【线程安全、 Future 设计模式、Master-Worker 设计模式 】(一)-全面详解(学习总结---从入门到深化)
多线程设计模式【线程安全、 Future 设计模式、Master-Worker 设计模式 】(一)-全面详解(学习总结---从入门到深化)
30 0
|
6天前
|
设计模式 Java 关系型数据库
认真学习设计模式之适配器模式(Adapter Pattern)/包装器模式
认真学习设计模式之适配器模式(Adapter Pattern)/包装器模式
70 0