设计模式(工厂模式,模板方法模式,单例模式)

单例模式:

确保一个类只有一个实例,并提供全局访问点。

单例模式举例:

  1. 配置信息类:用于存储应用程序的全局配置信息,例如数据库连接信息、日志配置等。

  2. 日志类:用于记录应用程序运行时的日志信息,确保在整个应用程序中只有一个日志实例

  3. 线程池类:在多线程环境下,使用单例模式可以确保只有一个线程池实例,提高资源利用率和性能。

单例模式饿汉式:

代码:

public class Singleton {
    /*
      防止外界随意使用构造方法new对象,我们需要将构造私有化
     */
    private Singleton(){

    }

    /*
       为了赶紧new对象,我们new对象的时候变成静态的,让其随着类的加载而加载
       为了不让外界随便使用类名调用此静态对象,我们将其变成private
     */
    private static Singleton singleton = new Singleton();

    /*
       为了将内部new出来的对象给外界
       我们可以定义 一个方法,将内部的对象返回给外界
     */
    public static Singleton getSingleton(){
        return singleton;
    }
}

将new出来的对象设置为静态属性,这样随着类的加载而加载

单例模式懒汉式:

public class Singleton1 {
    /*
      防止外界随意使用构造方法new对象,我们需要将构造私有化
    */
    private Singleton1() {

    }

    /*
       懒汉式,不着急new对象
     */
    private static Singleton1 singleton1 = null;

    /*
       为了将内部new出来的对给外界
       定义一个方法,将内部new出来的对返回
     */
    public static Singleton1 getSingleton1() {
        //如果singleton1不是null就没必要抢锁了,直接返回,是null再抢锁
        if (singleton1==null){
            synchronized (Singleton1.class){
                if (singleton1 == null) {
                    singleton1 = new Singleton1();
                }
            }
        }
        return singleton1;
    }
}

懒汉式就不着急new对象了,留了一个公共的接口,你想new的时候就new即可

懒汉式的线程不安全问题:

这也是懒汉式的一个缺点:如果没有加锁的代码:

public static Singleton1 getSingleton1() {
                if (singleton1 == null) {
                    singleton1 = new Singleton1();
                }
            
        return singleton1;
    }

这很容易引发线程不安全问题,我们设想有两个线程,第一个线程需要这个singleton1这个对象,进入了if判断,不过这个时候CPU将线程切换给了第二个线程,那这个时候,第二个线程也进入了if判断,然后CPU再切换会第一个线程,线程一创建了对象,但是我们知道线程二也进入了if判断,它也能创建对象,这就导致了线程不安全问题

饿汉式和懒汉式区别:

1:创建的时间不一样:饿汉式是在类加载过程中就创建了实例,而饿汉式是被调用的时候才创建实例

2:线程安全问题:饿汉式不存在什么线程安全,类加载的时候我就创建了,而且不能改,不可能又线程安全问题,反观饿汉式就有线程安全问题

在Spring中的单例模式的体现:

在 Spring 源码中,最常见的使用单例设计模式的场景就是在创建 Bean 实例时使用单例模式。Spring 容器默认情况下会将所有的 Bean 对象作为单例对象进行管理,这样可以节省资源,提高性能。

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
    
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    @Override
    public Object getSingleton(String beanName) {
        return this.singletonObjects.get(beanName);
    }
    
    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            Object oldObject = this.singletonObjects.get(beanName);
            if (oldObject != null) {
                throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName +
                        "': there is already object [" + oldObject + "] bound");
            }
            this.singletonObjects.put(beanName, singletonObject);
        }
    }
    
    // 其他方法...
}

这个是我在鱼皮公众号上看到的,我第一次看到这段话的时候,也是有一个疑问

创建 Bean 实例是饿汉式还是懒汉式?

然后我问了GPT:

Spring容器在启动时会预先实例化所有单例Bean对象,这样可以避免懒汉式中可能存在的线程安全问题,确保在需要使用Bean时能够立即获取到对象实例。这种预先实例化的方式类似于饿汉式,但并不完全等同于饿汉式的实现方式。


模板方法模式:

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。明确了一部分功能,而另一部分功能不明确。需要延伸到子类中实现

这个我觉得就非常好理解:

我们平常都在写的接口或者抽象类都是这种思想

比如我们要去餐馆吃饭,我们每次餐馆都要点菜买单

不过我们去不同的餐馆点的菜都不一样

就可以把餐馆抽象成一个类,不同的餐馆都是实现类

上一段代码:

public abstract class Hotel {
    public void eat(){
        System.out.println("点菜");
        eatCai();
        System.out.println("买单");
    }
    public abstract void eatCai();
}

public class QuanJuDe extends Hotel{
    @Override
    public void eatCai() {
        System.out.println("薄饼");
        System.out.println("放鸭肉");
        System.out.println("酱");
        System.out.println("葱丝");
        System.out.println("黄瓜丝");
        System.out.println("卷着吃");
    }
}
public class ZhangLiang extends Hotel{
    @Override
    public void eatCai() {
        System.out.println("调麻酱");
        System.out.println("放辣椒油");
        System.out.println("倒到大碗中吃");
    }
}

public class Test01 {
    public static void main(String[] args) {
        QuanJuDe quanJuDe = new QuanJuDe();
        quanJuDe.eat();

        System.out.println("================");

        ZhangLiang zhangLiang = new ZhangLiang();
        zhangLiang.eat();
    }
}

工厂模式:

工厂模式是一种创建型设计模式,其主要目的是封装对象的实例化过程,将对象的创建和使用分离。通过工厂模式,可以实现更灵活、可扩展的对象创建方式,同时降低代码的耦合度。

工厂模式分为下面三种:简单工厂模式,工厂方法模式,抽象工厂模式


还没有工厂的时候:我们如果需要车,我们得自己去造车 自己去 new 对象
public class BMW320 {
	public BMW320(){
		System.out.println("制造-->BMW320");
	}
}
 
public class BMW523 {
	public BMW523(){
		System.out.println("制造-->BMW523");
	}
}
 
public class Customer {
	public static void main(String[] args) {
		BMW320 bmw320 = new BMW320();
		BMW523 bmw523 = new BMW523();
	}
}
简单工厂模式:简单工厂的时候,我们已经有了简单的工厂,我们不用自己去造车了

我们可以告诉工厂,我们需要这个这个车,工厂造好给我们即可

有一个工厂类,我们去调用工厂类的造车方法造车

产品类:

// 产品接口
interface Product {
    void doSomething();
}

// 具体产品类 A
class ConcreteProductA implements Product {
    @Override
    public void doSomething() {
        System.out.println("Product A is doing something.");
    }
}

// 具体产品类 B
class ConcreteProductB implements Product {
    @Override
    public void doSomething() {
        System.out.println("Product B is doing something.");
    }
}

工厂类:

// 简单工厂类
class SimpleFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        }
        return null;
    }
}

客户端代码:

// 客户端代码
public class Main {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.doSomething();

        Product productB = SimpleFactory.createProduct("B");
        productB.doSomething();
    }
}
工厂方法模式:到了这个时候,随着车型的增多,一个工厂已经不能生成这么多车型了

就需要工厂分类:每个工厂生成一种型号的车

有一个工厂抽象类,生成各种型号的车的工厂去继承里面的造车方法

再有一个车的抽象类,不同的车去继承里面的方法

// 产品接口
interface Product {
    void doSomething();
}

// 具体产品类 A
class ConcreteProductA implements Product {
    @Override
    public void doSomething() {
        System.out.println("Product A is doing something.");
    }
}

// 具体产品类 B
class ConcreteProductB implements Product {
    @Override
    public void doSomething() {
        System.out.println("Product B is doing something.");
    }
}

// 工厂接口
interface Factory {
    Product createProduct();
}

// 具体工厂类 A,负责创建产品 A
class ConcreteFactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂类 B,负责创建产品 B
class ConcreteFactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.doSomething();

        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.doSomething();
    }
}
抽象工厂模式:这个时候的需求就已经很复杂了,

每个车需要的零件都不同,比如车1和车2分别是两个不同的型号,车1需要空调a和发动机b,车2需要空调b和发动机b

这个时候就设计到了一个产品族,就是空调,发动机或者其它产品合在一起就是一个产品族

有点像我们日常生活中开店,比如我们开冷冻产品店,那我们不可能一个人去准备所有的冷冻产品,我肯定是去找对应的供货商,比如火锅料的供货商,鱿鱼的供货商,饮料的供货商,然后整合到我这个冷冻店再去销售

所以翻译成Java语言就是,空调是一个抽象类,发动机是一个抽象类,多个抽象类,一个工厂抽象类,不同型号的车是一个类都去继承这个工厂,你需要什么零件就去这个工厂里面配这个零件。

// 产品族接口
interface AbstractProductA {
    void doSomething();
}

interface AbstractProductB {
    void doSomething();
}

// 具体产品类 A1
class ConcreteProductA1 implements AbstractProductA {
    @Override
    public void doSomething() {
        System.out.println("Product A1 is doing something.");
    }
}

// 具体产品类 B1
class ConcreteProductB1 implements AbstractProductB {
    @Override
    public void doSomething() {
        System.out.println("Product B1 is doing something.");
    }
}

// 具体产品类 A2
class ConcreteProductA2 implements AbstractProductA {
    @Override
    public void doSomething() {
        System.out.println("Product A2 is doing something.");
    }
}

// 具体产品类 B2
class ConcreteProductB2 implements AbstractProductB {
    @Override
    public void doSomething() {
        System.out.println("Product B2 is doing something.");
    }
}

// 抽象工厂接口
interface AbstractFactory {
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}

// 具体工厂类 1
class ConcreteFactory1 implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }
}

// 具体工厂类 2
class ConcreteFactory2 implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB2();
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        AbstractProductB productB1 = factory1.createProductB();
        productA1.doSomething();
        productB1.doSomething();

        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        AbstractProductB productB2 = factory2.createProductB();
        productA2.doSomething();
        productB2.doSomething();
    }
}
相关推荐
暗黑起源喵39 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
wrx繁星点点8 小时前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
金池尽干10 小时前
设计模式之——观察者模式
观察者模式·设计模式
也无晴也无风雨10 小时前
代码中的设计模式-策略模式
设计模式·bash·策略模式
捕鲸叉19 小时前
MVC(Model-View-Controller)模式概述
开发语言·c++·设计模式
wrx繁星点点19 小时前
享元模式:高效管理共享对象的设计模式
java·开发语言·spring·设计模式·maven·intellij-idea·享元模式
凉辰19 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
菜菜-plus20 小时前
java设计模式之策略模式
java·设计模式·策略模式
暗黑起源喵20 小时前
设计模式-迭代器
设计模式
lexusv8ls600h21 小时前
微服务设计模式 - 网关路由模式(Gateway Routing Pattern)
spring boot·微服务·设计模式