23种设计模式简单记录

23种设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。下面是这些设计模式的概览:

创建型模式(Creational Patterns)

  1. 单例模式(Singleton):确保一个类只有一个实例,并提供一个全局访问点。
  2. 工厂方法模式(Factory Method):定义一个用于创建对象的接口,但让子类决定实例化哪一个类。
  3. 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  4. 建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  5. 原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。

结构型模式(Structural Patterns)

  1. 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。
    1. MusicPlayerAdapter 类作为适配器,它实现了 PlayMusicV2 接口,并在内部持有一个 PlayMusicV1 对象的引用。当客户端调用 play 方法时,适配器会根据传入的参数调用旧接口的 playMp3 方法,从而实现了接口的转换,让旧的音频播放器库能够适应新的应用程序接口。例子:
      // 原有的接口
      interface PlayMusicV1 {void playMp3(String filename);
      }// 新的接口
      interface PlayMusicV2 {void play(String audioType, String filename);
      }// 第三方库的实现类
      class OldMusicPlayer implements PlayMusicV1 {@Overridepublic void playMp3(String filename) {System.out.println("Playing MP3 file: " + filename);}
      }// 适配器类
      class MusicPlayerAdapter implements PlayMusicV2 {private final PlayMusicV1 player;public MusicPlayerAdapter(PlayMusicV1 player) {this.player = player;}@Overridepublic void play(String audioType, String filename) {if ("mp3".equalsIgnoreCase(audioType)) {player.playMp3(filename);} else {System.out.println("Unsupported audio type: " + audioType);}}
      }// 客户端代码
      public class Client {public static void main(String[] args) {PlayMusicV1 oldPlayer = new OldMusicPlayer();PlayMusicV2 adapter = new MusicPlayerAdapter(oldPlayer);// 使用新接口播放MP3adapter.play("mp3", "favorite_song.mp3");}
      }

  2. 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  3. 组合模式(Composite):允许你将对象组合成树形结构来表示整体/部分层次结构。
  4. 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责。
  5. 外观模式(Facade):为子系统中的一组接口提供一个一致的界面,简化接口。
  6. 享元模式(Flyweight):运用共享技术有效支持大量细粒度的对象。
  7. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。
    1. 代理模式通过提供一个代理对象来控制对真实对象的访问,这个代理对象可以在访问真实对象前进行一些预处理操作,或者在访问后进行一些后续处理。下面是一个简单的Java代理模式示例,我们以租房为例,说明静态代理和动态代理的实现。

      静态代理示例

      首先定义一个租房服务的接口:

      1public interface RentHouse {
      2    void rent();
      3}

      接着实现这个接口的真实对象(房东):

      1public class RealEstate implements RentHouse {
      2    @Override
      3    public void rent() {
      4        System.out.println("房东出租房子");
      5    }
      6}

      然后创建一个静态代理类,也实现相同的接口:

      1public class HouseAgency implements RentHouse {
      2    private RealEstate realEstate;
      3
      4    public HouseAgency(RealEstate realEstate) {
      5        this.realEstate = realEstate;
      6    }
      7
      8    @Override
      9    public void rent() {
      10        preProcess();
      11        realEstate.rent();
      12        postProcess();
      13    }
      14
      15    private void preProcess() {
      16        System.out.println("中介进行房源展示、咨询等前期工作");
      17    }
      18
      19    private void postProcess() {
      20        System.out.println("中介完成合同签订等后续工作");
      21    }
      22}

      最后是客户端代码,使用代理来租房:

      1public class Client {
      2    public static void main(String[] args) {
      3        RealEstate realEstate = new RealEstate();
      4        RentHouse proxy = new HouseAgency(realEstate);
      5        proxy.rent();
      6    }
      7}

      动态代理示例

      动态代理通常使用Java的java.lang.reflect.Proxy类来创建代理对象,这里使用JDK动态代理为例:

      首先,保持RentHouse接口和RealEstate类不变。

      动态代理类如下:

      1import java.lang.reflect.InvocationHandler;
      2import java.lang.reflect.Method;
      3import java.lang.reflect.Proxy;
      4
      5public class DynamicProxy implements InvocationHandler {
      6    private Object target;
      7
      8    public Object bind(Object target) {
      9        this.target = target;
      10        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
      11                target.getClass().getInterfaces(), this);
      12    }
      13
      14    @Override
      15    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      16        preProcess();
      17        Object result = method.invoke(target, args);
      18        postProcess();
      19        return result;
      20    }
      21
      22    private void preProcess() {
      23        System.out.println("动态代理:中介进行房源展示、咨询等前期工作");
      24    }
      25
      26    private void postProcess() {
      27        System.out.println("动态代理:中介完成合同签订等后续工作");
      28    }
      29}

      客户端代码调整为:

      1public class Client {
      2    public static void main(String[] args) {
      3        RealEstate realEstate = new RealEstate();
      4        DynamicProxy dynamicProxy = new DynamicProxy();
      5        RentHouse proxy = (RentHouse) dynamicProxy.bind(realEstate);
      6        proxy.rent();
      7    }
      8}

      在这个例子中,无论是静态代理还是动态代理,代理对象都在真实对象执行租房操作前后增加了额外的行为,如房源展示、合同签订等,体现了代理模式的价值。动态代理相比静态代理更加灵活,可以在运行时动态创建代理对象,无需为每个真实对象都手动创建一个代理类。

行为型模式(Behavioral Patterns)

  1. 责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
  2. 命令模式(Command):将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。
  3. 解释器模式(Interpreter):给定一种语言,定义它的文法和一个解释器,该解释器使用该语法来解释语言中的句子。
  4. 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。
  5. 中介者模式(Mediator):用一个中介者对象来封装一系列的对象交互。
  6. 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
  7. 观察者模式(Observer):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
  8. 状态模式(State):允许一个对象在其内部状态改变时改变它的行为。
  9. 策略模式(Strategy):定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。
  10. 模板方法模式(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。
  11. 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。

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

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

相关文章

Swift - Hello World

文章目录 Swift - Hello World1. Hello World Swift - Hello World 1. Hello World 不用编写main函数,Swift将全局范围内的首句可执行代码作为程序入口一句代码尾部可以省略分号(;),多句代码写到同一行时必须用分号(…

docker容器通俗理解

前言 如果大家没使用过Docker,就在电脑上下载一个VMware Workstation Pro,创建一个虚拟机安装一个windows操作一下感受一下,为什么我的电脑上还以再安装一台windows主机?其实你可以理解为Docker就是Linux系统的一个虚拟机软件。 我的Windows也可以安装…

【高校科研前沿】东北地理所孙敬轩博士为一作在《中国科学:地球科学(中英文版)》发文:气候变化下东北地区农业绿水安全风险评估

目录 01 文章简介 02 研究内容 03 文章引用 04 期刊简介 01 文章简介 论文名称:Risk assessment of agricultural green water security in Northeast China under climate change(气候变化下东北地区农业绿水安全风险评估) 第一作者及…

unity计算三维空间下点到线,点到面,线到线,线到面,面到面最短距离的点的方法

通用的一个方法GetDistance&#xff0c;计算两个点的距离&#xff0c;不开平方 /// <summary> /// 获取两个点的距离&#xff0c;不开平方 /// </summary> /// <param name"a"></param> /// <param name"b"></param>…

猫咪冻干究竟怎么选不踩雷?这几款生骨肉冻干一定适合你家喵

315中国之声的报道揭示了河北省邢台市南和区某宠粮代工厂的“行业秘密”&#xff0c;这无疑给广大宠物主人敲响了警钟。配料表上标注的鸡肉含量高达52%&#xff0c;新鲜鸡小胸占20%&#xff0c;然而所谓的鲜鸡肉实际上却是鸡肉粉。我们养宠物本是为了心灵上的慰藉&#xff0c;但…

栈和队列总结

文章目录 前言一、栈和队列的实现1.栈的具体实现2.循环顺序队列的具体实现 二、栈和队列总结总结 前言 T_T此专栏用于记录数据结构及算法的&#xff08;痛苦&#xff09;学习历程&#xff0c;便于日后复习&#xff08;这种事情不要啊&#xff09;。所用教材为《数据结构 C语言版…

揭秘Linux文件系统

前言 在上一篇文件描述符详解中谈论的都是打开的文件&#xff0c;但是在我们的系统中不仅有打开的文件还有许多未打开的文件&#xff0c;那么这些未打开的文件又该如何理解呢?阅读完本篇文章相信你会得到答案。 如果觉得文章内容对你有所帮助的话&#xff0c;可以给博主一键三…

langfuse使用零星记录

目录 前言 一、langfuse是什么&#xff1f; 二、使用零星记录 1.评估打分 2.score的问题与解决 总结 前言 langfuse使用过程的一些坑点&#xff0c;做一些记录&#xff0c;便于日后回顾查找&#xff0c;也为同样在学习的小伙伴们异同一些可能的帮助。 期望在学习使用一…

centos7.9离线安装rke2

使用rke2安装k8s,master节点有三台&#xff0c;agent节点一台&#xff0c;三台master通过etcd存储保证master节点的高可用&#xff0c;使用nginx对master进行负载均衡。 主机清单如下 ip主机名称用途192.168.16.72node72server节点192.168.16.73node73master节点192.168.16.7…

常用excel操作笔记

一、表达式 1. 查找excel中一列值出现在另外一列中 IF(SUMPRODUCT(--(ISNUMBER(SEARCH($A$1:$A$101,C2)))),1,0) 2.计算某个字符出现的次数 LEN(G2)-LEN(SUBSTITUTE(G2,">",))1 3.拼接字符串 C2&"|"&A2 4.根据当前日期生成19位id TEXT(TODAY…

MySQL语句,使用replace替换数据后,有小数时,使用round等方法无法取整

15.55这个数字 replace替换数据后乘以100&#xff0c;在Navicat中运行&#xff0c;是显示整数 但是在Python中调用SQL语句&#xff0c;使用replace替换数据并乘以100后&#xff0c;会显示有一位小数&#xff0c;并且使用round等方法无法取整 最终采用cast函数将replace后的数…

新装电脑Flutter环境部署坑汇总(持续更新)

1.本地安装&#xff0c;安装fvm的坑 本人电脑使用windows &#xff0c;安装fvm则一般使用choco安装&#xff0c;那么首先需要安装choco,打开powershell/或者cmd运行以下命令&#xff1a; Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager…

5.2 海思SS928开发 - kernle开发 - 构建脚本

5.2 kernle开发 - 构建脚本 SS928 kernel 提供了 makefile 用于 kernel 构建。想要得到最后的内核镜像&#xff0c;还要经过许多步骤&#xff0c;每次都手敲命令的话&#xff0c;会把我累死。自己实现一个构建脚本&#xff0c;支持以下常用功能即可&#xff1a; 构建内核镜像配…

图像置乱加密-Arnold加密算法

置乱加密是另一种较常用的加密方法&#xff0c;现也被许多文献选用&#xff0c;置乱加密可以是以像素为单位进行全局置乱&#xff0c;该方式打乱了图像像素值的位置&#xff0c;使其图像内容失去相关性&#xff0c;达到保护的目的。也可以是以块为单位进行置乱&#xff0c;该方…

Kafka报错ERROR Exiting Kafka due to fatal exception during startup

报错&#xff1a; ERROR Exiting Kafka due to fatal exception during startup. (kafka.Kafka$) kafka.common.InconsistentClusterIdException: The Cluster ID FSzSO50oTLCRhRnRylihcg doesnt match stored clusterId Some(0oSLohwtQZWbIi73YUMs8g) in meta.properties. Th…

某宝因SSL证书过期无法正常访问,证书过期问题频发企业如何破局?

近日&#xff0c;有网友发现&#xff0c;某宝网站无法正常访问&#xff0c;出现“此连接非私人连接”提示&#xff0c;而导致此类提示的罪魁祸首是因为SSL证书过期&#xff01;其实&#xff0c;近年来&#xff0c;因SSL证书过期导致的网站无法正常访问的事件频频发生&#xff0…

vue2—— mixin 超级详细!!!

mixin Mixin是面向对象程序设计语言中的类&#xff0c;提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类 Mixin类通常作为功能模块使用&#xff0c;在需要该功能时“混入”&#xff0c;有利于代码复用又避免了多继承的复杂 vue中的mixin 先来看一下官方定义 mi…

YOLO-yolov5构建数据集

1.收集数据集 创建一个dataset文件夹用来存放图片数据集。 我这里使用的图片数据集&#xff0c;是对一段视频进行抽帧得到的200张狗狗图片。 在dataset文件夹下新建images和labels文件夹&#xff0c;并将200张狗狗图片放入images中。 2.标注数据集 2.1安装标注工具labelimg…

Jenkins邮件发送失败问题解决

如下提示为 Extended E-mail Notification开启Debug模式下显示的错误信息&#xff0c; (Debug模式设置方法&#xff1a;Dashboard-> manage Jenkins->configure System)DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 DEB…

Projector投影器-Unity使用Projector投影器实现简单的阴影

在Unity中&#xff0c;可以使用Projector投影器来实现简单的阴影效果。Projector投影器是一种用于在场景中投射纹理的组件&#xff0c;可以用来模拟光照、阴影等效果。 要使用Projector投影器实现阴影效果&#xff0c;可以按照以下步骤进行操作&#xff1a; 创建一个空对象&am…