Java设计模式总结

《武林外传》老白曾经说过这样一句话。高手就是手里无刀,心中也无刀。 类似于设计模式,你不知不觉中已经融进你的代码中了,但你并不知已经运用了。下面我总结几个我觉得比较常用的设计模式。

1:设计模式分类

总体来说设计模式分为三大类:

创建型模式, 共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式, 共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式, 共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

大家没有必要死记硬背哪一种模式属于哪一种类型,面试如果问到,因为不会背而挂,只能说这家公司不去也罢。

我们需要真正理解,为什么工厂方法模式也是创建型模式,因为它是一个factory,他创建一个对象供你使用。又比如适配器模式为什么是结构型模式,它是不是从”顺序性编码“变成了”分支形编码“,改变了代码的结构。所以你需要真正理解每一种设计模式,做到不自觉的运用到你的代码中去。

2:单例模式

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

//懒汉 线程不安全
class SingletonDemo1 {

    private SingletonDemo1(){}

    private static SingletonDemo1 instance = null;

    public static SingletonDemo1 getInstance() {
        if (instance == null) {
            instance = new SingletonDemo1();
        }
        return instance;
    }
}

//懒汉 线程安全 直接加锁
class SingletonDemo2 {

    private SingletonDemo2() {}

    private static SingletonDemo2 instance = null;

    public static synchronized SingletonDemo2 getInstance() {
        if (instance == null) {
            instance = new SingletonDemo2();
        }
        return instance;
    }
}

// Double Check
public class SingletonDemo2 {
    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;
    }
}


//饿汉 线程安全
class SingletonDemo3 {

    private SingletonDemo3() {}

    private static SingletonDemo3 instance = new SingletonDemo3();

    public static SingletonDemo3 getInstance() {
        return instance;
    }
}

//内部类 线程安全,并且懒加载
class SingletonDemo4 {

    private SingletonDemo4() {}

    private static class InnerSingletonDemo4 {
        private static final SingletonDemo4 instance = new SingletonDemo4();
    }

    public static final SingletonDemo4 getInstance() {
        return InnerSingletonDemo4.instance;
    }
}

// 枚举方式。最为推荐的一种方式
public enum SingletonDemo5 {
    INSTANCE;

    public void doSomeThing() {
    }
}

3: 适配器模式

举个例子,比较插头的电源为110v,但是我们现在想要220v的电源。所以我们就可以用适配器模式,使这个类符合我现有的要求。

同样,在编写JAVA程序时,我们可能会遇到这样一种情况:我们需要一个类A来实现接口B,但是类A并没有实现接口B中的所有方法,而类A是不能被改变的,这时我们可以创建一个类C,它继承类A并实现接口B,这个类C就是一个适配器。适配器中的代码将接受你所拥有的接口,并产生你所需要的接口。适配器模式有两张:类适配器模式和对象适配器模式。

// 假设这个规定电源为220v
interface A {

    void method220v();

}

//这个类实现的为110v的方法
class B {

    void method110v() {
        System.out.println("110v");
    }
}

// 适配为既可以110v,也可以220v
class C extends B implements A {

    @Override
    public void method220v() {

        System.out.println("220v");
    }
}

4:装饰着模式

装饰者模式通过组合的方式扩展对象的特性,这种方式允许我们在任何时候对对象的功能进行扩展甚至是运行时扩展,而若我们用继承来完成对类的扩展则只能在编译阶段实现,所以在某些时候装饰者模式比继承(inheritance)要更加灵活。

所谓装饰者,实际上就是将装饰的内容的以零部件的形式构建起来,然后经过组装形成一个一个新的逻辑内容,动态而灵活的组建逻辑性能。

// 形状
Shape circle = new Circle();

// 加了红色的形状
Shape redCircle = new RedShapeDecorator(new Circle());
  
// 加了红色的长方形
Shape redRectangle = new RedShapeDecorator(new Rectangle());

5:策略模式

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

应用实例:

  • 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。

  • 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。

  • JAVA AWT 中的 LayoutManager。

优点:

  • 算法可以自由切换。

  • 避免使用多重条件判断。

  • 扩展性良好。

缺点:

  • 策略类会增多。

  • 所有策略类都需要对外暴露。

使用场景:

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

  • 一个系统需要动态地在几种算法中选择一种。

  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。举一个例子:很简单的一个例子。比如人,人分为男人,女人,甚至不清楚性别的人。但这三种类型的人,都有不同的行为。那么我们在描述这些不同行为的时候,一般我们做法就是如下:

if (male) {
   //...
} else if (female) {
   //...
} else {
   //...
}

类似如上。很多个if,else进行嵌套。这样非常的难看,不优雅。如果我们用策略模式替换,会怎么样。

  • 第一步,定义一个Person类接口

  • 第二步定义person的继承类,如男人,女人等等

  • 第三步定义一个enum类,表示可选择性。

  • 最后一步定义一个策略选择器

public interface Person {
    void executeStrategy();
}

public class MalePerson implements Person {
    public void executeStrategy() {
        System.out.println("我是男性");
    }
}

public class FemalePerson implements Person {
    public void executeStrategy() {
        System.out.println("我是女性");
    }
}

public class UnknownPerson implements Person {
    public void executeStrategy() {
        System.out.println("未知性别");
    }
}


public enum SexEnum {
    MALE("male", "男性"),
    FEMALE("female", "女性"),
    UNKNOWN("unknown", "未知");

    private String code;
    private String sex;

    SexEnum(String code, String sex) {
        this.code = code;
        this.sex = sex;
    }
}

// 这块在实际开发中,我们会用factory结合spring来做这块逻辑
public class ContextStrategy {
    private MalePerson malePerson = new MalePerson();
    private FemalePerson femalePerson = new FemalePerson();
    private UnknownPerson unknownPerson = new UnknownPerson();

    public Person getPersonStrategy(SexEnum sexEnum) {
        if ("male".equals(sexEnum.getCode())) {
            return malePerson;
        } else if ("female".equals(sexEnum.getCode())) {
            return femalePerson;
        } else {
            return unknownPerson;
        }
    }
}


public class Main {
    public static void main(String[] args) {
        ContextStrategy strategy = new ContextStrategy();
        strategy.getPersonStrategy(**SexEnum.MALE**).executeStrategy();
        strategy.getPersonStrategy(**SexEnum.FEMALE**).executeStrategy();
        strategy.getPersonStrategy(**SexEnum.UNKNOWN**).executeStrategy();
    }
}

// 结果如下:
// 我是男性
// 我是女性
// 未知性别

其实我们可以看到。策略选择器是传入一个Enum类,然后根据传入Enum的不同,选择了不同的继承类。从而实现了if else。优雅的过渡。可以看到,代码非常的优雅易懂,主代码,没有if else分支。但同时代码量多了起来。不过也很容易维护。

在实际项目中,我们一般会使用工厂模式 + 策略模式一起使用来达到减少if else的操作,策略模式在实际使用中非常的多,建议同学们务必掌握。

6:责任链模式

// 校验器接口
public interface Validator<T> {
    Validator<T> next();
    boolean handle(T t) throws FordealException;
}

public class BasicParameterValidator implements Validator<ValuationWO> {
    @Autowired
    private Validator<ValuationWO> tokenValidator;

    @Override
    public Validator<ValuationWO> next() {
        return tokenValidator;
    }

    @Override
    public boolean handle(ValuationWO valuationWO) throws Exception {
        return next().handle(valuationWO);
    }
}

最后

以上举了几个简单的例子,做一个抛砖引玉,还是希望同学们可以花一点时间,去了解下比较常用的设计模式。不需要背下来,多看看别人写的代码,然后尝试去模仿,慢慢的,你就会发觉,你就开始融会贯通了。做到手里无刀,心中也无刀,但实际上又快有准。

文章转载自:程序员博博

原文链接:https://www.cnblogs.com/wenbochang/p/8834587.html

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

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

相关文章

小程序内的分包与数据共享

一:数据共享 小程序内的数据共享和vue当中不一样,vue当中的vue实例可以使得所有的组件都能this.store 但是小程序它只有page对象,和组件实例对象.对于vue而言,vue实例可以使得添加的组件都有. 但是page对象页面对象,不能使得页面内部有.只能使得这个页面内能访问.vue实例,会…

桌面上怎么记工作任务更加合理?能设置桌面提醒的便签软件

在快节奏的现代工作中&#xff0c;电脑已成为我们处理工作的主要工具。每天&#xff0c;我们都要面对电脑屏幕&#xff0c;处理大量的工作任务。为了更好地管理这些琐碎却重要的工作&#xff0c;将工作任务直接记录在桌面上&#xff0c;随时查看和调整&#xff0c;无疑是一种高…

自定义注解+AOP切面实现日志记录

自定义注解&#xff1a; Target(ElementType.METHOD)// 作用在方法上 Retention(RetentionPolicy.RUNTIME) Documented Inherited // 子类可以继承此注解 public interface OperationLog { } aop切面&#xff1a; Slf4j Aspect Component public class OperationAspect {Au…

【Text2SQL 论文】评估 ChatGPT 的 zero-shot Text2SQL 能力

论文&#xff1a;A comprehensive evaluation of ChatGPT’s zero-shot Text-to-SQL capability ⭐⭐⭐⭐ arXiv:2303.13547 这篇论文呢综合评估了 ChatGPT 在 zero-shot Text2SQL 任务上的表现。 dataset 使用了 Spider、Spider-SYN、Spider-DK、Spider-Realistic、Spider-CG…

SQL刷题笔记day6-1

1从不订购的客户 分析&#xff1a;从不订购&#xff0c;就是购买订单没有记录&#xff0c;not in 我的代码&#xff1a; select c.name as Customers from Customers c where c.id not in (select o.customerId from Orders o) 2 部门工资最高的员工 分析&#xff1a;每个部…

SFOS2:组件介绍

一、前言 在sailfish os application的开发过程中&#xff0c;几乎是困难重重&#xff0c;因为我暂未找到具有完整性、指导性、易懂性的开发文档&#xff0c;特别是组件的使用&#xff0c;现决定将自己的探究结果记录下来。因此&#xff0c;这篇文章只会具有参考价值&#xff0…

[数据集][目标检测]道路井盖下水道井盖开关闭和检测数据集VOC+YOLO格式407张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;407 标注数量(xml文件个数)&#xff1a;407 标注数量(txt文件个数)&#xff1a;407 标注类别…

swift中json和字典Dict或者数组相互转换,JSONSerialization的强大使用

在Swift中&#xff0c;你可以使用JSONSerialization类将JSON字符串转换为字典。要将 Swift 字典转换为 JSON 字符串&#xff0c;我们可以使用JSONSerialization类的data(withJSONObject:options:)方法。这个方法将字典转换为二进制数据&#xff0c;然后我们可以使用String(data…

20 VUE学习:插件

介绍 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。下面是如何安装一个插件的示例&#xff1a; import { createApp } from vueconst app createApp({})app.use(myPlugin, {/* 可选的选项 */ })一个插件可以是一个拥有 install() 方法的对象&#xff0c;也可以直接…

股票量化交易上手,一个特别简单却长期可用的交易策略,官方接口

股票实现程序化自动化交易的三个基础&#xff1a;获取数据、执行交易、查询账户。 以后说到策略示例的时候就不介绍接口的基础使用方法了&#xff0c;随便一个策略把过程写出来都会很啰嗦&#xff0c;尽量压缩内容吧&#xff0c;这些内容是面向新手的&#xff0c;大佬们忽略细节…

基于51单片机的酒精浓度检测仪的设计

一.硬件方案 硬件部分为利用MQ3气敏传感器测量空气中酒精浓度&#xff0c;并转换为电压信号&#xff0c;经A/D转换器转换成数字信号后传给单片机系统&#xff0c;由单片机及其相应外围电路进行信号的处理&#xff0c;显示酒精浓度值以及超阈值声光报警。电路主要由51单片机最小…

自学SPSS,有哪些教学视频或书籍推荐?

书籍推荐 经过长达八年的不断迭代与优化&#xff0c;SPSSAU的用户群体已经远超简单的数据分析层面&#xff0c;而是逐步深入到了学术研究的精髓之中。如今&#xff0c;无论是在SCI、EI等国际权威学术期刊&#xff0c;还是北大核心期刊、CSSCI等国内顶尖学术期刊上&#xff0c;…

Django学习

1.pycharm社区版创建django PyCharm社区版如何创建Django项目并运行_pycharm社区版打开django-CSDN博客 2.Django TemplateDoesNotExist: rest_framework 当我们使用djangorestframework框架时&#xff0c;首先下载pip install djangorestframework 参考博文Django Templat…

LeetCode算法题:560. 和为 K 的子数组(Java)

给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a;nums [1,2,3], …

做视频号小店和达人对接的好,爆单少不了!

大家好&#xff0c;我是喷火龙。 目前&#xff0c;视频号是没有什么自然流量的&#xff0c;所以&#xff0c;想要出单、爆单的话&#xff0c;靠达人带货的方式才是最可靠的&#xff0c;靠达人带货是肯定要对接达人&#xff0c;并和达人沟通带货的。 下面给大家讲一讲应该怎么…

Vue 前端加框 给div加红色框框 js实现

实现方式&#xff1a;用getElementsByClassName、createElement、appendChild实现在原有div上添加一个新的div&#xff0c;从而达到框选效果 <template><div><el-button click"addIten">添加</el-button><el-button click"deleteIt…

云动态摘要 2024-05-29

给您带来云厂商的最新动态&#xff0c;最新产品资讯和最新优惠更新。 最新优惠与活动 [免费试用]大模型知识引擎体验招募 腾讯云 2024-05-21 大模型知识引擎产品全新上线&#xff0c;为回馈新老客户&#xff0c;50万token免费送&#xff0c;开通服务即领取&#xff01; 云服…

摩尔线程MTT S4000 AI GPU助力30亿参数大模型训练,性能比肩英伟达同类解决方案

中国国产GPU制造商摩尔线程(Moore Threads)在AI加速器领域取得了显著进展&#xff0c;其最新推出的MTT S4000 AI GPU在训练大规模语言模型时表现突出&#xff0c;据称相较于其前代产品有着显著的性能提升。根据cnBeta的报道&#xff0c;搭载S4000 GPU的全新“酷鹅千卡智能计算集…

贷款借钱平台 小额贷款系统开发小额贷款源码 贷款平台开发搭建

这款是贷款平台源码/卡卡贷源码/小贷源码/完美版 后台51800 密码51800 数据库替换application/database.php程序采用PHPMySQL&#xff0c;thinkphp框架代码开源&#xff0c;不加密后台效果&#xff1a;手机版效果 这款是贷款平台源码/卡卡贷源码/小贷源码/完美版 后台51800 密码…

SAP 生产订单报工函数BAPI_PRODORDCONF_CREATE_TT不返回报错信息

最近财务一直反馈MES报工的数据都没有成本,然后去查看原因发现是财务当月的KP26的价格没有进行维护,导致没有收集到工单的报工成本。 但是在前台操作CO11 报工的时候,系统会给出报错的信息 但是我们在调用函数BAPI_PRODORDCONF_CREATE_TT的时候,系统并没有返回报错的信息…