Java设计模式很难吗,这篇带你熟悉设计模式

news2025/1/22 21:07:21

3.1 概述

可以发现,设计模式好像都是类似的。越看越感觉都着不多。其实都是类似面向接口编程的一种体现,只不过侧重点不一样或者说要体现的结果不一样。

3.2 使用场景

问题一:应对可能变化的对象实现

方案:间接创建

模式:工厂模式

问题二:为请求指定相应的操作(类似请假审批,不同时长对应不同职位的审批人)

方案:程序根据请求动态选择操作

模式:责任链模式

3.3 具体说明

3.3.1 策略模式

  • 策略模式说明

一个行为型模式,包含多个行为或职责的业务,通过策略模式简化

public class StrategyContext {
    Strategy strategy;
    public StrategyContext(Strategy strategy) {
        this.strategy = strategy;
    }
    /**
     * 
     */
    public int context(int a, int b) {
        return strategy.operator(a,b);
    }
}

策略模式的核心为StrategyContext上下文类,持有strategy对象,在context完成操作。

  • 策略模式实践

如何使用策略模式解决大量使用if else 或大量switch问题,策略模式+反射。

策略模式后好像使用都还是要用if else来决定调用哪个类,所以在引入策略模式后,在上下文类还要增加反射。

public class StrategyContext {
    Strategy strategy;
    public StrategyContext(String type) throws Exception {
        Class clazz = Class.forName(type);
        this.strategy = (Strategy) clazz.newInstance();
    }
    /**
     * 
     */
    public int context(int a, int b) {
        return strategy.operator(a,b);
    }

当然这里的type可以用个枚举来解决。感觉代价非常大是不是没必要,不过代码的可读性还是增强了。

p.s. 在框架里策略模式中的Context一般不会直接出现,类似spring中直接在使用时就通过注解给设置了

3.3.2、装饰器模式

描述:原接口Shape不变,方法数量不变,在方法实现中增加修饰

场景:

场景一:一个类功能简单,满足不了我们的需求

场景二:给原方法增加日志功能,不改变原方法,新的实现类去实现此功能,带入的对象为接口对象

特点

  • 原接口Shape不动,增加新的装饰类ShapeDecorator
  • 原方法名不变,只是增加或修饰此方法体
  • ColorShapeDecorator装饰类持有原对象,只是增加了修饰
public class ColorShapeDecorator extends ShapeDecorator {
    public ColorShapeDecorator(Shape shape) {
        super(shape);
    }
    @Override
    public void draw() {
        setColor();
        shape.draw();
    }
    private void setColor() {
       //设置画图颜色
    }
}

3.3.3 代理模式

设置一个中间代理来控制访问原目标对象,达到增强原对象的功能和简化访问方式的目的

场景:

场景一:不改变原方法,对原方法增加耗时的计算

场景二:rpc远程调用,client端进行动态代理类似耗时计算一样,用户不用关心client的具体实现

分类

  • 静态代理模式
  • 动态代理模式

说明

  • 静态代理模式
/**
 * 与适配器模式的区别,适配器模式主要改变所考虑对象的接口,
 * 而代理模式不能改变所代理类的接口。与装饰器模式的区别,
 * 装饰器模式是为了增强功能,代理模式是为了加以控制
 */
public class ProxySigntureService implements SigntureService {
    private SigntureService signatureService;
    /**
     * Default constructor
     */
    public ProxySigntureService(SigntureService signatureService) {
        this.signatureService = signatureService;
    }
    public void sign() {
        //控制对这个对象的访问
        // 实现电子签名
    }
}
  • 动态代理模式
public class DynamicProxySignatureService implements InvocationHandler {
    private Object obj;
    public DynamicProxySignatureService(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxyObj, Method method, Object[] objects) 
           throws Throwable {
        return method.invoke(obj,objects);
    }
}

参考文章:https://blog.csdn.net/liujiahan629629/article/details/19428485

3.3.4 适配器模式

描述:原接口不变,增加方法数量

场景:

场景一:原接口不变,在基础上增加新的方法。

场景二:接口的抽象方法很多,不想一一实现,使用适配器模式继承原实现类,再实现此接口

  • 适配器模式适合需要增加一个新接口的需求,在原接口与实现类基础上需要增加新的接口及方法。类似原接口只能method01方法,需求是增加method02方法,同时不再使用之前接口类。

新接口

public interface Targetable {
    /**
     * 
     */
    public void method01();
    /**
     * 
     */
    public void method02();
}

原接口实现类

public class Source {
    public void method01() {
        // TODO implement here
    }
}

适配器类,用于实现新接口。继承原实现类,同时实现新接口。

public class Adapter extends Source implements Targetable {
    /**
     * 
     */
    public void method02() {
        // TODO implement here
    }
}

测试类

public class AdapterTest {
    public static void main(String[] args) {
        Targetable targetable = new Adapter();
        targetable.method01();
        targetable.method02();
    }
}

3.3.5 单例模式

保证被创建一次,节省系统开销。

1)单例实现方式

  • 饿汉式
  • 懒汉式
  • 懒汉式+synchronized
  • 双重校验
  • 静态内部类
  • 枚举(推荐方式)

2)实现代码

  • 饿汉式
package com.hanko.designpattern.singleton;
/**
 * 饿汉式 (饿怕了,担心没有吃,所以在使用之前就new出来)
 *优点:实现简单,安全可靠
 *缺点:在不需要时,就已实例化了
 * @author hanko
 * @version 1.0
 * @date 2020/9/14 18:50
 */
public class HungrySingleton {
    //特点一 静态私有变量 直接初始化
    private static HungrySingleton instance = new HungrySingleton();
    //特点二 构造函数私有
    private HungrySingleton(){
    }
    public static HungrySingleton getInstance(){
        return instance;
    }
    public void doSomething(){
        //具体需要实现的功能
    }
}
  • 懒汉式
package com.hanko.designpattern.singleton;
/**
 * 懒汉式(非常懒,所以在要使用时再去new)
 *优点:简单
 *缺点:存在线程安全问题
 * @author hanko
 * @version 1.0
 * @date 2020/9/14 18:50
 */
public class SluggardSingleton {
    //特点一 静态私有变量,先不初始化
    private static SluggardSingleton instance;
    //特点二 构造函数私有
    private SluggardSingleton(){
    }
    //特点三 null判断,没有实例化就new
    public static SluggardSingleton getInstance(){
        if(instance == null){
            instance = new SluggardSingleton();
        }
        return instance;
    }
    public void doSomething(){
        //具体需要实现的功能
    }
}
  • 懒汉式+Synchronized
package com.hanko.designpattern.singleton;
/**
 * 懒汉式(非常懒,所以在要使用时再去new)
 *优点:简单
 *缺点:存在线程安全问题
 * @author hanko
 * @version 1.0
 * @date 2020/9/14 18:50
 */
public class SluggardSingleton {
    //特点一 静态私有变量,先不初始化
    private static SluggardSingleton instance;
    //特点二 构造函数私有
    private SluggardSingleton(){
    }
    //特点三 null判断,没有实例化就new
    public static synchronized SluggardSingleton getInstance(){
        if(instance == null){
            instance = new SluggardSingleton();
        }
        return instance;
    }
    public void doSomething(){
        //具体需要实现的功能
    }
}
  • 双重校验
package com.hanko.designpattern.singleton;
/**
 * 双重校验
 *对懒汉式单例模式做了线程安全处理增加锁机制
 * volatile变量级
 * synchronized 类级
 * @author hanko
 * @version 1.0
 * @date 2020/9/15 9:53
 */
public class DoubleCheckSingleton {
    //特点一 静态私有变量,增加volatile变量级锁
    private static volatile DoubleCheckSingleton instance;
    //特点二 构造函数私有
    private DoubleCheckSingleton(){
    }
    //特点三 双重null判断  synchronized类级锁
    public static DoubleCheckSingleton getInstance(){
        if (instance == null){
            synchronized(DoubleCheckSingleton.class){
                if (instance == null){
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}
  • 静态内部类
package com.hanko.designpattern.singleton;
/**
 * 内部静态类方式
 *优点:静态内部类不会在InnerStaticSingleton类加载时加载,
 * 而在调用getInstance()方法时才加载
 *缺点:存在反射攻击或者反序列化攻击
 * @author hanko
 * @version 1.0
 * @date 2020/9/15 10:03
 */
public class InnerStaticSingleton {
    //特点一:构造函数私有
    private InnerStaticSingleton(){
    }
    //特点二:静态内部类
    private static class InnerSingleton{
        private static InnerSingleton instance = new InnerSingleton();
    }
    public InnerSingleton getInstance(){
        return InnerSingleton.instance;
    }
    public void doSomething(){
        //do Something
    }
}
  • 枚举(推荐方式)
package com.hanko.designpattern.singleton;
/**
 * 枚举实现单例简单安全
 *
 * @author hanko
 * @version 1.0
 * @date 2020/9/14 19:01
 */
public enum EnumSingleton {
    INS;
    private Singleton  singleton;
    EnumSingleton() {
        singleton = new Singleton();
    }
    public void doSomething(){
          singleton... 
        //具体需要实现的功能
    }
}
EnumSingleton.INS.doSomething();

3.3.6 工厂模式

(简单工厂、抽象工厂):解耦代码。

简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力。

工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品。

抽象工厂:用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族。

参考文章:几种常用的设计模式--工厂模式 - 知乎

3.3.7 观察者模式

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

3.3.8 外观模式

提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。

3.3.9 状态模式

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。与策略模式类似,策略模式侧重点在一个事的不同实现方式抽离出来,而状态模式是一个事的不同状态抽离出来(开始、进行中、结束),每次状态完成自己的业务逻辑。

3.4 总结:

  • 适配器模式(原功能不变,增加新功能)、装饰器模式(装饰原功能)、代理模式(控制原功能)
  • 策略模式侧重点在一个事的不同实现方式抽离出来,而状态模式是一个事的不同状态抽离出来(开始、进行中、结束),每次状态完成自己的业务逻辑。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pycharm远程连接服务器

遇到的问题: 在服务器上配环境 流程: 先安装anaconda(去其官网下载个脚本文件到服务器上,然后启动脚本即可) bash Anaconda3-5.3.1-Linux-x86_64.sh然后创建 python环境 conda create -n pytorch python3.10去pyt…

【Linux】搞懂进程地址空间

文章目录1、从程序地址空间开始1.1 在C/C中看到的地址实际是?1.2 感性理解虚拟地址空间2、进程地址空间2.1 进程地址空间是怎样被描述的?2.2 进程地址空间和内存的关系2.3 为什么需要进程地址空间?1、从程序地址空间开始 1.1 在C/C中看到的地…

并发:线程状态

java的线程状态分为六种 新建 NEW 当一个线程对象被创建,但是还没有调用start方法时处于新建状态 此时未与操作系统底层线程关联 可运行 RUNNABLE 调用了start方法,就会由新建进入可运行状态 此时与底层线程关联,由操作系统调度执行 &…

python就是学不会怎么办?

编程从来都不是只看,只照葫芦画瓢就能学会的学科要想学会,必须是要有你个人是思考的,学会掌握编程逻辑,在学的过程中想为什么这么写,应该怎么去实现这个功能,拆分为几步不断的实操练习才能让你真的掌握知识…

并发,并行,串行,同步,异步,进程,进程池,线程,线程池

并发,并行,串行,同步,异步,进程,进程池,线程,线程池 进程 什么是进程: 开发写的代码称之为程序,将程序运行起来,就是进程 进程是申请一块内存空…

vue中动态引入图片为什么要是require, 你不知道的那些事

相信用过vue的小伙伴,肯定被面试官问过这样一个问题:在vue中动态的引入图片为什么要使用require 有些小伙伴,可能会轻蔑一笑:呵,就这,因为动态添加src被当做静态资源处理了,没有进行编译,所以要加上require, 我倒着都能背出来… emmm… 乍一看好像说的很有道理啊,但…

Linux实现文件定期本地备份/异地备份/删除备份的脚本

一.背景 1.总会出出现环境上的数据丢失,在没有备份的情况下会非常的被动,不管是由于病毒还是人为的原因造成的程序、数据被删除,有时候后悔已经来不及,不如提前做到数据的备份,而异地备份也更加的保险一点。 2.数据备…

【Servlet】1:踏入JavaWeb的第一把钥匙

目录 第一章 | JavaWeb序章 | 章节概述 | JavaWeb项目运行流程 | 静态与动态资源 | Javaweb开发人员的三个任务 第二章 | HTTP网络协议 | 章节概述 | HTTP简介 | HTTP请求三要素 | HTTP请求包、响应包 | HTTP状态码 | HTTPS vs HTTP 本文章属于后端全套笔记的第三部…

Jenkins 如何 使用企业权限 登录

实现方式 基于Jenkins的 “CAS Plugin” 和 “Role-based Authorization Strategy”插件实现 CAS Plugin: 该插件支持使用CAS作为身份验证源,以支持单点登录(SSO)。一般的,企业都会有 这么一个服务,提供企业 统一身份管理,比如 百…

【GlobalMapper精品教程】026:影像黑边白边出现的原因及解决办法汇总

本文讲解Globalmapper中,影像黑边白边出现的原因及解决办法汇总。 文章目录 1. 影像黑边白边出现的原因2. 影像黑边白边的解决方法1. 影像黑边白边出现的原因 通常,由于影像格式、像素深度、无效值、背景值等原因,会产生黑边或者白边,给影像的拼接或者裁剪带来困扰。 2. …

基于ERP集成的流程制造管理系统

ERP的含义是企业资源计划,含义是对企业所拥有各种资源进行综合规划和优化管理,用以降低成本,提高效率,增加利润。ERP最初是在90年代初提出的,那时的ERP概念,还只是根据计算机技术的发展和供需链管理,推论各…

什么是GEMM?该怎么去学习GEMM?

什么是GEMM? 它的英文全称是 GEneral Matrix to Matrix Multiplication (通用矩阵的矩阵乘法),Gemm在神经网络的计算中占据很重要的位置。 它代表全局矩阵到矩阵的乘法,它本质上完全按照它在tins上所说的那样,将两个输入矩阵乘法在…

批量替换网站程序中的gotoip域名

网站访问出现验证页面,这是因为网站调用了二级域名,西部数码二级域名用于测试访问效果,不能用于正式访问,但是有些用户网站调试安装时使用了二级域名,内部链接没有修改,所以访问调用出现了验证页面。 这时要检查网站后…

DBCO(二苯并环辛炔)DBCO-PEG16-Benzylamine特点分享

【产品描述】 DBCO-PEG16-Benzylamine固体状,长链小分子PEG点击试剂,DBCO(二苯并环辛炔)是一种环炔烃,可以通过在水溶液中通过应变促进的1,3-偶极环加成反应与叠氮化物反应,这种生物正交反应也称为无铜点击…

前端、vue、Vue3弹幕实现;前端CSS实现弹幕

前端基于CSS3实现弹幕 基于CSS3动画 根据 Google Developer,渲染线程分为 主线程 (main thread) 和 合成线程 (compositor thread)。如果 CSS 动画只是改变 transforms 和 opacity,这时整个 CSS 动画得以在 合成线程 完成(而JS动画则会在 主…

PTA题目 最佳情侣身高差

专家通过多组情侣研究数据发现,最佳的情侣身高差遵循着一个公式:(女方的身高)1.09 (男方的身高)。如果符合,你俩的身高差不管是牵手、拥抱、接吻,都是最和谐的差度。 下面就请你写个…

HTTP Only限制XSS盗取cookie

今天继续给大家介绍渗透测试相关知识,本文主要内容是HTTP Only限制XSS盗取cookie。 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果自负! 再次强调:严禁对…

使用 Helm Cli 将 chart 推送到 Harbor

使用 Helm Cli 将 chart 推送到 Harbor 背景问题 努力寻找适用于特定版本的 Harbor 和 Helm 的文档。 我尝试添加我的仓库(repo) helm repo add harbor https://myharbor.mydomain.com/chartrepo/myproject --username myusername --password mypass…

NXP iMX8M Plus M7核心FreeRTOS开发

By Toradex胡珊逢 Toradex 的 Verdin iMX8M Plus 计算机模块采用 NXP 的 iMX8M Plus 处理器。该 CPU 除了有支持 AI 硬件加速单元的 NPU 外,还配置了一个 M7 微控制器。相比于 iMX 8 QuadMax 处理器上时钟频率为 266MHz 的M4 微控制器, 该M7 的时钟频率…

Java基础39 Object类(节选)

ObjectObject类一、 equals( )● 与 equals的对比(☆)二、hashCode( )三、toString( )四、finalize( )Object类 Object类:Java中lang包的类,是类层次结构的根类,每个类都使用Object作为超类。所有对象(包…