java23种设计模式

一、单例模式

单例模式一共有8种,除了常见的饿汉式,懒汉式,还有双重检查(实际开发中推荐使用),静态内部类

1、双重检查 voliated和 synchronized 的组合使用(推荐使用)

volatile:多个线程拿到一个共享变量,如果一个线程改变了共享变量里面的值,则其他的线程的共享变量的值也发生改变
例子:

package voliteaed;

/**
 * <简述>
 * <详细描述>
 *
 * @author LiuShanshan
 * @version $Id$
 */
public class Singleton {
    private static volatile Singleton singleton;
    private Singleton(){

    }
    public static Singleton getInstance(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}

线程安全;延迟加载;效率较高

2、静态内部类(推荐使用,jvm帮我们控制线程安全)

package voliteaed;

/**      静态内部类
 * <简述>
 * <详细描述>
 *
 * @author LiuShanshan
 * @version $Id$
 */
public class StaticSingleton {
    public static void main(String[] args) {
        SingletonDemo1 instance = SingletonDemo1.getInstance();
        SingletonDemo1 instance2 = SingletonDemo1.getInstance();
        System.out.println(instance == instance2);
    }
}
// 使用静态内部类生成对象
class  SingletonDemo1{
    private SingletonDemo1(){

    }

    private  static class singletonDemo2{
        private final static SingletonDemo1 singletoDemo1 = new SingletonDemo1();
    }

    public static SingletonDemo1 getInstance(){
        return singletonDemo2.singletoDemo1;
    }
}

避免了线程不安全,利用静态内部类特点实现延迟加载,效率高

3、枚举(推荐使用)

例子:

package voliteaed;

/**   枚举的方式实现单例
 * <简述>
 * <详细描述>
 *
 * @author LiuShanshan
 * @version $Id$
 */
public class EnumDmo1 {
    public static void main(String[] args) {
        Demo1 sfsd = Demo1.SFSD;
        Demo1 sfsd1 = Demo1.SFSD;
        System.out.println(sfsd == sfsd1);
        sfsd.get();
    }
}
enum Demo1{
    SFSD;
    public void get(){
        System.out.println("枚举方式使用单例");
    }
}

  1. 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
  2. 这种方式是Effective Java作者Josh Bloch 提倡的方式

jdk源码中体现

在RunTime中体现了饿汉式
在这里插入图片描述

二、工厂模式

1、简单工厂模式

简单工厂模式的核心相当于在 7种设计方式最上面图的提供者那边又新增了一个类(工厂类),提供者可以新增类,新增的类处理业务,使用者不变,所以如果后面增加的提供者,也只需要更改工厂类代码,而不是动使用者代码
如图所示:
在这里插入图片描述

2、工厂方法模式

工厂方法模式的运用为写几个类(工厂方法)继承使用方(使用方为抽象类),调用方使用的时候,创建工厂方法对象即可。
在这里插入图片描述

3、抽象工厂模式

1、创建抽象类或者接口,继承他们或者实现他们的叫做抽象工厂类,使用方里面聚合抽象类(作为属性注入进去),然后调用方调用使用方,传入对应的工厂类对象即可
在这里插入图片描述

4、观察者模式

参考博客:https://blog.csdn.net/CSDN2497242041/article/details/120403205

java中Observable是抽象目标类(被观察的类),Observer是接口,继承了这个类就代表类为观察者。

Observable 类是抽象目标类,它有一个 Vector 向量,用于保存所有要通知的观察者对象,下面来介绍它最重要的 3 个方法。

  1. void addObserver(Observer o) 方法:用于将新的观察者对象添加到向量中。
  2. void notifyObservers(Object arg) 方法:调用向量中的所有观察者对象的 update()
    方法,通知它们数据发生改变。通常越晚加入向量的观察者越先得到通知。
  3. void setChange() 方法:用来设置一个 boolean类型的内部标志位,注明目标对象发生了变化。当它为真时,notifyObservers() 才会通知观察者。

三、原型模式(克隆模式)

注意点:需要克隆的类,需要实现 cloneable接口,不然报错java.lang.CloneNotSupportedException
例子:

1、浅拷贝

package 原型模式;

/**
 * <简述>
 * <详细描述>
 *
 * @author LiuShanshan
 * @version $Id$
 */
public class Yuanxing implements Cloneable{
    private String name;
    private String age;

    public Yuanxing(String name, String age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Yuanxing{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 拷贝当前对象
        Yuanxing clone = null;
        try {
            clone = (Yuanxing)super.clone();
        } catch (Exception e){
            e.printStackTrace();
        }
        return clone;
    }
}

2、深拷贝(推荐使用序列化的方式)

例如:

package 原型模式;

import jdk.jfr.events.ExceptionThrownEvent;

import java.io.*;

/**
 * <简述>
 * <详细描述>
 *
 * @author LiuShanshan
 * @version $Id$
 */
public class Yuanxing implements Serializable,Cloneable{

    private String name;
    private String age;
    private YuanxingObject yuanxingObject;

    public Yuanxing(){
        super();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public YuanxingObject getYuanxingObject() {
        return yuanxingObject;
    }

    public void setYuanxingObject(YuanxingObject yuanxingObject) {
        this.yuanxingObject = yuanxingObject;
    }

    @Override
    public String toString() {
        return "Yuanxing{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 拷贝当前对象
        Yuanxing clone = null;
        clone = (Yuanxing)super.clone();
        if(yuanxingObject != null){
            clone.setYuanxingObject((YuanxingObject)yuanxingObject.clone());
        }
        return clone;
    }

    /**
     *<简述> 深clone
     *<详细描述>
     * @author Liushanshan
     * @param
     * @return 原型模式.Yuanxing
    */
    public Yuanxing cloneDeep() throws IOException, ClassNotFoundException {
        ObjectOutputStream oos;
        ByteArrayOutputStream bos;
        ObjectInputStream ois;
        ByteArrayInputStream bis;
        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);  // 放入当前对象
            oos.flush();
            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            Yuanxing yuanxing = (Yuanxing)ois.readObject();
            return yuanxing;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}

总结

缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了ocp原则,这点请同学们注意.

四、建造者模式

1、建造者模式的4个角色:

在这里插入图片描述

2、建造者模式图解(将通用的作为抽象类里面的抽象方法,其他的作为对象放入抽象类中作为属性)

在这里插入图片描述

3、jdk中StringBuilder源码追踪

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值