设计模式实践

一、工厂模式

这里只讲简单工厂模式,详细的可以参考Java工厂模式(随笔)-CSDN博客。工厂类会根据不同的参数或条件来决定创建哪种对象,这样客户端只需要知道自己需要什么对象,而不需要关心对象的创建过程!

代码实现如下

1)首先是Phone接口

package factory;


/**
 * @author heming
 * @date 2024/5/31
 * 抽象电话的接口
 */
public interface Phone {
    /**
     * 抽象的打电话的功能,有不同的实现类做具体的实现
     */
    void call();
}

2)创建几个实现接口的方法的手机类方便测试

 2.1、创建华为手机类

package factory;


/**
 * @author heming
 * @date 2023/5/31
 */
public class HuaweiPhone implements Phone {

    @Override
    public void call() {
        System.out.println("使用华为手机打电话");
    }
}

2.2、创建IPhone手机类

package factory;

/**
 * @author heming
 * @date 2024/5/31
 */
public class IPhone implements Phone {

    @Override
    public void call() {
        System.out.println("使用Iphone打电话");
    }
}

2.3、创建MIphone手机类

package factory;


/**
 * @author heming
 * @date 2023/5/31
 */
public class MiPhone implements Phone {

    @Override
    public void call() {
        System.out.println("使用MiPhone打电话");
    }
}

3)创建简单工厂模式类

通过简单工厂模式类实现相关业务逻辑

package factory;

/***
 * @Date(时间)2023-05-31
 * @Author heming
 *
 * 简单工厂模式类
 */
public class SimpleFactoryPattern {
    /**
     * 简单的工厂
     * @param name 需要创建对象的名称
     * @return
     */
    public static Phone create(String name) {
        //根据输入对象名称判断返回相匹配的对象
        if("IPhone".equals(name)) {
            //返回对象
            return new IPhone();
        }else if("MiPhone".equals(name)) {
            return new MiPhone();
        }else if("HuaweiPhone".equals(name)) {
            return new HuaweiPhone();
        }

        return null;
    }

}

代码测试:

package factory;

/***
 * @Date(时间)2023-06-01
 * @Author heming
 */
public class Mains {
    public static void main(String[] args) {
        Phone phone = SimpleFactoryPattern.create("IPhone");
        phone.call();

        Phone phone2 = SimpleFactoryPattern.create("MiPhone");
        phone2.call();

        Phone phone3 = SimpleFactoryPattern.create("HuaweiPhone");
        phone3.call();
    }
}

二、单例模式

单例模式是一种常见的设计模式,可以确保一个类只有一个实例,并提供全局访问点。在合适的情况下,合理使用单例模式可以提高系统的性能和可维护性。

在Java中,可以使用以下几种方式来实现单例模式:

  1. 饿汉式

public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {
        // 私有构造方法
    }

    public static Singleton getInstance() {
        return instance;
    }
}
  1. 懒汉式(线程安全)

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // 私有构造方法
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  1. 懒汉式(双重检查锁定)

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {
        // 私有构造方法
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  1. 静态内部类

public class Singleton {
    private Singleton() {
        // 私有构造方法
    }

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

三、代理设计模式

代理模式在 AOP 中的应用

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。

四、模板方法模式

模板方法模式是一种行为设计模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤的实现方式。

package template;

public abstract class Template {
    //这是我们的模板方法
    public final void TemplateMethod(){
        PrimitiveOperation1();
        PrimitiveOperation2();
        PrimitiveOperation3();
    }

    protected void  PrimitiveOperation1(){
        //当前类实现
        System.out.println("PrimitiveOperation1");
    }

    //被子类实现的方法
    protected abstract void PrimitiveOperation2();
    protected abstract void PrimitiveOperation3();

}

package template;

public class TemplateImpl extends Template {

    @Override
    public void PrimitiveOperation2() {
        //当前类实现
        System.out.println("PrimitiveOperation2");
    }

    @Override
    public void PrimitiveOperation3() {
        //当前类实现
        System.out.println("PrimitiveOperation3");
    }
}

验证

package template;

public class TemplateMain {
    public static void main(String[] args) {
        Template template = new TemplateImpl();
        template.PrimitiveOperation1();
        template.PrimitiveOperation2();
        template.PrimitiveOperation3();
    }
}

Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。一般情况下,我们都是使用继承的方式来实现模板模式,但是 Spring 并没有使用这种方式,而是使用Callback 模式与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性。

五、观察者模式

观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。

Spring 事件驱动模型中的三种角色

事件角色

ApplicationEvent (org.springframework.context包下)充当事件的角色,这是一个抽象类,它继承了java.util.EventObject并实现了 java.io.Serializable接口。

Spring 中默认存在以下事件,他们都是对 ApplicationContextEvent 的实现(继承自ApplicationContextEvent):

  • ContextStartedEventApplicationContext 启动后触发的事件;

  • ContextStoppedEventApplicationContext 停止后触发的事件;

  • ContextRefreshedEventApplicationContext 初始化或刷新完成后触发的事件;

  • ContextClosedEventApplicationContext 关闭后触发的事件。

技术图片

事件监听者角色

ApplicationListener 充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()方法来处理ApplicationEventApplicationListener接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 ApplicationEvent就可以了。所以,在 Spring中我们只要实现 ApplicationListener 接口实现 onApplicationEvent() 方法即可完成监听事件

package org.springframework.context;
import java.util.EventListener;
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E var1);
}
事件发布者角色

ApplicationEventPublisher 充当了事件的发布者,它也是一个接口。

@FunctionalInterface
public interface ApplicationEventPublisher {
    default void publishEvent(ApplicationEvent event) {
        this.publishEvent((Object)event);
    }

    void publishEvent(Object var1);
}

ApplicationEventPublisher 接口的publishEvent()这个方法在AbstractApplicationContext类中被实现,阅读这个方法的实现,你会发现实际上事件真正是通过ApplicationEventMulticaster来广播出去的。具体内容过多,就不在这里分析了,后面可能会单独写一篇文章提到。

Spring 的事件流程总结

  1. 定义一个事件: 实现一个继承自 ApplicationEvent,并且写相应的构造函数;

  2. 定义一个事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法;

  3. 使用事件发布者发布消息: 可以通过 ApplicationEventPublisher 的 publishEvent() 方法发布消息。

Example:

package mode.observe;

import org.springframework.context.ApplicationEvent;

// 定义一个事件,继承自ApplicationEvent并且写相应的构造函数
public class DemoEvent extends ApplicationEvent {
    private static final long serialVersionUID = 1L;

    private String message;

    public DemoEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}
package mode.observe;

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

// 定义一个事件监听者,实现ApplicationListener接口,重写 onApplicationEvent() 方法;
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {

    //使用onApplicationEvent接收消息
    @Override
    public void onApplicationEvent(DemoEvent event) {
        String msg = event.getMessage();
        System.out.println("接收到的信息是:"+msg);
    }

}
package mode.observe;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

// 发布事件,可以通过ApplicationEventPublisher  的 publishEvent() 方法发布消息。
@Component
public class DemoPublisher {

    @Autowired
    ApplicationContext applicationContext;

    public void publish(String message){
        //发布事件
        applicationContext.publishEvent(new DemoEvent(this, message));
    }
}

测试类如下:

当调用 DemoPublisher 的 publish() 方法的时候,比如 demoPublisher.publish("你好") ,控制台就会打印出:接收到的信息是:你好 。

六、适配器模式

七、装饰者模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/526569.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Golang 开发实战day06 - Boolean Conditional

&#x1f3c6;个人专栏 &#x1f93a; leetcode &#x1f9d7; Leetcode Prime &#x1f3c7; Golang20天教程 &#x1f6b4;‍♂️ Java问题收集园地 &#x1f334; 成长感悟 欢迎大家观看&#xff0c;不执着于追求顶峰&#xff0c;只享受探索过程 Golang 教程06 - Boolean &a…

分布式锁的原子性问题

4.6 分布式锁的原子性问题 更为极端的误删逻辑说明&#xff1a; 线程1现在持有锁之后&#xff0c;在执行业务逻辑过程中&#xff0c;他正准备删除锁&#xff0c;而且已经走到了条件判断的过程中&#xff0c;比如他已经拿到了当前这把锁确实是属于他自己的&#xff0c;正准备删…

如何在CentOS安装Nexus容器无公网IP远程管理本地仓库

文章目录 1. Docker安装Nexus2. 本地访问Nexus3. Linux安装Cpolar4. 配置Nexus界面公网地址5. 远程访问 Nexus界面6. 固定Nexus公网地址7. 固定地址访问Nexus Nexus是一个仓库管理工具&#xff0c;用于管理和组织软件构建过程中的依赖项和构件。它与Maven密切相关&#xff0c;可…

数据通讯平台解决方案(Word原件获取)

1.数据通讯平台方案 1.1.系统概述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 系统机构图 2.2.业务架构设计 (1) MQ消息服务 (2) TCP通讯服务 (3) CoAP通讯服务 (4) MQTT通讯服务 (5) 资源管理服务 2.3.主流技术架构分析 纵向设计方案 2.4…

QGraphics框架场景中图元的移除与析构

1.场景里面使用removeItem函数&#xff0c;这个函数官方给出如下解释 注意这个词remove只是移除&#xff0c;并不是delete掉&#xff0c;所以只是场景中&#xff08;显示出来的图元&#xff09;没有了&#xff0c;空间还是存在。 举个代码例子&#xff1a; void MyGraphicsV…

USACO 2024 Open Bronze铜组题解

迟到了一个月的题解...... Logical Moos: 啊这题放在铜组T1雀食有点BT...... 首先&#xff0c;我们关注l前第一和r最后那两组。如果这俩有一个是true&#xff0c;那答案肯定也是true。 否则&#xff0c;在l和r外边的都是false。那我们就只用仔细看l和r中间的玩意儿。对于l和…

三月以来的黄金暴涨 ,华尔街都看不懂

本轮黄金大幅上涨无法按照美联储政策逻辑解释&#xff0c;央行的购金需求也无法合理化金价的历史新高&#xff0c;而金价的大涨也与黄金ETF流出相背&#xff0c;推动反弹的“神秘力量”令分析师困惑不已。 黄金上涨的情况往往会出现在美联储开启降息周期后&#xff0c;如果市场…

Linux 之 定时任务调度器-crond(crontab)服务

Linux系列文章&#xff1a; Windows本地如何添加域名映射&#xff1f;&#xff08;修改hosts文件&#xff09;_本机域名映射-CSDN博客 Linux安装mysq 8.0服务端和客户端(亲测保成功&#xff09;_linux安装mysql客户端-CSDN博客 linux-man命令的使用及练习_man命令执行后无法…

微服务架构下,如何通过弱依赖原则保障系统高可用?

前言 当我初次接触高可用这个概念的时候&#xff0c;对高可用的【少依赖原则】和【弱依赖原则】的边界感模糊&#xff0c;甚至有些“傻傻分不清楚”。这两个原则都关注降低模块之间的依赖关系&#xff0c;但它们之间的确存在某些差异。 那么&#xff0c;「少依赖原则」和「弱…

Windows深度学习环境----Cuda version 10.2 pytorch3d version 0.3.0

Requirements Python version 3.8.5Pytorch version: pytorch1.6.0 torchvision0.8.2 torchaudio0.7.0 cudatoolkit10.2.89pytorch3d version 0.3.0Cuda version 10.2 感觉readme文件里的不适配&#xff0c;跟pytorch官网不同 以前的 PyTorch 版本 |PyTorch的 # CUDA 10.2 c…

面板数据回归模型(二)房价的影响因素分析

1.数据来源 本文选择我国出一线城市房价均值、新一线城市房价均值、二线城市房价均值、货币供应量和利率。选取2002-2018年的数据,共17组数据,由于数据的自然对数变换不改变原有的协整关系,并能使其趋势线性化,消除时间序列中存在的异方差现象,所以对所有数据取其自然对数…

程序员简历程序员简历.pdf

你们在制作简历时&#xff0c;是不是基本只关注两件事&#xff1a;简历模板&#xff0c;还有基本信息的填写。 当你再次坐下来更新你的简历时&#xff0c;可能会发现自己不自觉地选择了那个“看起来最好看的模板”&#xff0c;填写基本信息&#xff0c;却没有深入思考如何使简历…

聊一下Redis实现分布式锁的8大坑

前两篇文章都在讲 Redis 的 5 大常用数据类型&#xff0c;以及典型的 10 大应用场景。 那么今天就来看看 Redis 实现分布式锁。 聊一聊Redis实现分布式锁的8大坑 Redis中5大常见数据类型用法 工作中Redis用的最多的10种场景 在分布式系统中&#xff0c;保证资源的互斥访问是…

新火种AI|拳打百度,脚踢阿里...令国产大模型危机感爆棚的kimi强势上线!

作者&#xff1a;小岩 编辑&#xff1a;冰冰 Sora大火后&#xff0c;生成式AI的高光时候终于轮到了国产大模型。2024年3月&#xff0c;Kimi智能助手在市场上掀起了一股狂热的热潮。 Kimi是由时下大火的AI初创公司——北京月之暗面科技有限公司所推出的一款智能助手&#xff…

自动化测试框架 - Unittest 学习笔记速查

文章目录 UnitTest 简介UnitTest 核心UnitTest 原理UnitTest 断言函数TestCase&#xff08;用例&#xff09;基本用法执行结果 TestFixture&#xff08;夹具&#xff09;方法级夹具类级夹具模块级夹具 TestSuite&#xff08;套件&#xff09;TestLoader&#xff08;加载器&…

文件/目录的权限和归属

一.文件/目录的权限和归属的简要分析与概括 1.程序访问文件时的权限&#xff0c;取决于此程序的发起者 * 进程的发起者&#xff0c;同文件的属主&#xff1a;则应用文件属主权限 *进程的发起者&#xff0c;属于文件属组&#xff1b;则应用文件属组权限 *应用文件“其它”权…

【云贝教育】Oracle 19c OCP 083题库解析(71)

本文为云贝教育郭一军&#xff08;微信&#xff1a;guoyJoe&#xff09;原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 71、Which two are true about an Oracle gold image-based installation in Oracle…

指尖论文靠谱不 #学习方法#媒体#职场发展

指尖论文是当前市场上一款非常实用的论文写作、查重、降重工具。许多学生、研究人员和教师都已经开始使用它&#xff0c;因为它相当靠谱、方便、易用且高效。 首先&#xff0c;指尖论文的查重功能非常强大&#xff0c;能够及时准确地检测出文本中的相似内容&#xff0c;帮助用户…

源清天木生物科技带您抢先体验2024国际生物发酵展

参展企业介绍 优质的种质资源是生物产业的核心&#xff0c;也是农业的核心&#xff01; 高效的选育优质的种质资源&#xff0c;是生物产业和农业最重要工作之一。 天木生物&#xff0c;致力于高效生物育种技术开发和特色生物育种装备开 发&#xff0c;并依托自主研发的技术和装…

揭秘强大的文件同步利器Rsycn

目录 引言 一、Rsycn基础介绍 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;特性 &#xff08;三&#xff09;同步方式 &#xff08;四&#xff09;服务备份角色 &#xff08;五&#xff09;命令工具 &#xff08;六&#xff09;配置格式 &#xff…