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

news/2024/8/26 14:18:51 标签: 设计模式

单例模式:

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

单例模式举例:

  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();
    }
}


http://www.niftyadmin.cn/n/5558977.html

相关文章

美式键盘 QWERTY 布局的起源

注&#xff1a;机翻&#xff0c;未校对。 The QWERTY Keyboard Is Tech’s Biggest Unsolved Mystery QWERTY 键盘是科技界最大的未解之谜 It’s on your computer keyboard and your smartphone screen: QWERTY, the first six letters of the top row of the standard keybo…

langchain 入门指南(二)- 如何跟大模型对话

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 本文中&#xff0c;我们会通过一个简单的例子来展示如何使用 langchain 来调用大模型的 chat API&#xff08;使用 Chat Model&#xff…

一树枇杷一树金,湖光山色湖光深 ——西安工程大学赴陕西安康“筑梦乡村,携手同行”暑期社会实践团

“谋三农福祉促乡村振兴”。为涵养家国情怀&#xff0c;激发使命担当&#xff0c;西安工程大学暑期实践团赴陕西安康&#xff0c;开展“筑梦乡村&#xff0c;携手同行”社会实践&#xff0c;于7.16 日前往瀛湖镇清泉村。 实践团队于当日早8:30准时在市政府公交车站集合&#xf…

AI时代:探索个人潜能的新视角

文章目录 Al时代的个人发展1 AI的高速发展意味着什么1.1 生产力大幅提升1.2 生产关系的改变1.3 产品范式1.4 产业革命1.5 Al的局限性1.5.1局限一:大模型的幻觉1.5.2 局限二&#xff1a;Token 2 个体如何应对这种改变?2.1 职场人2.2 K12家长2.3 大学生2.4 创业者 3 人工智能发展…

人才盘点要多少钱?

很多公司谈到TD&#xff0c;最多的话题就是识别高潜&#xff0c;即HiPos&#xff08;High Potentials&#xff09;。对于识别高潜&#xff0c;有5个核心问题需要搞清楚&#xff1a; 1&#xff0c;什么是HiPos 2&#xff0c;HiPos的价值 3&#xff0c;如何识别HiPos 4&#…

Tongweb7 日志报错:HttpServletResponse is exceeding the 65535 bytes limit(by lqw)

遇到jsp访问的时候页面加载不全&#xff0c;看tw7日志有如下图信息&#xff1a; 原因&#xff1a; jsp的本质是servlet&#xff0c;编译时会先将他转换成java代码&#xff0c;然后再进行编译。 你的jsp编译成生成的文件太大&#xff0c;导致报错。&#xff08;Java 编译器限制…

深度学习计算机视觉中,如何理解feature maps的channel?

在深度学习的计算机视觉领域&#xff0c;特征图&#xff08;feature maps&#xff09;是卷积神经网络&#xff08;CNN&#xff09;中非常重要的概念。理解特征图的通道&#xff08;channel&#xff09;可以帮助你更好地理解网络如何从图像中提取和表示信息。 什么是特征图的通…

网络安全-网络安全及其防护措施5

21.互联网交换点&#xff08;ISP) IXP的定义和作用 互联网交换点&#xff08;IXP&#xff09;是一个物理基础设施&#xff0c;通过它&#xff0c;互联网服务提供商&#xff08;ISP&#xff09;和内容提供商可以互相交换互联网流量。IXP的目的是提高网络性能、降低带宽成本和减…