23种设计模式简单记录

devtools/2024/10/18 5:56:29/

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.ppmy.cn/devtools/23428.html

相关文章

基于Springboot+Mybatis-Plus+mysql+html旅游网站

博主介绍: 大家好,本人精通Java、Python、C#、C、C编程语言,同时也熟练掌握微信小程序、Php和Android等技术,能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验,能够为学生提供各类…

力扣HOT100 - 78. 子集

解题思路&#xff1a; class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> lists new ArrayList<>(); // 解集lists.add(new ArrayList<Integer>()); // 首先将空集加入解集中for(int i 0; i < n…

hadoop中块的概念

块概念 目录 1.分块的原因 2.分块的大小 默认为128M 3.机架 4.在块的分布上 5.hadoop上传数据的步骤&#xff08;重要&#xff09; 6.读过程 1.分块的原因 存储的角度 分布式存储 计算角度 生产环境中 4G 2.分块的大小 默认为128M 块的大小不宜过大 也不宜过小 都会使…

vue的build先上部署的 devServer不生效的场景记录

文章目录 Nginx 相关命令VUE项目devServer.proxy&#xff08;正向代理&#xff09;匹配请求中的地址工作流程开发期间代理proxy的配置项目打包上线出现的问题描述 Nginx 相关命令 //运行命令 start nginx 启动nginx服务//运行命令 nginx -s stop 停止nginx服务//运行命令 ngin…

司库是什么?和资金管理有什么异同?

一、司库是什么&#xff1f; 司库&#xff0c;从广义上来说&#xff0c;是一个企业或机构的资金管理中心&#xff0c;负责集中管理和调度企业的资金、资产和负债。它不仅涉及到企业的现金流管理、风险管理、投资决策等方面&#xff0c;还涉及到企业与外部金融机构、供应商、客…

Hadoop-Hive-Spark-离线环境搭建

一、版本描述 apache-hive-2.3.9-bin.tar.gz hadoop-2.7.0.tar.gz spark-2.4.0-bin-hadoop2.7.tgz 下载链接&#xff1a; https://archive.apache.org/dist/spark/spark-2.4.0/spark-2.4.0-bin-hadoop2.7.tgz https://archive.apache.org/dist/hadoop/common/hadoop-2.7.…

STM32使用PWM控制舵机

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 舵机简介 2. 硬件连接 3. 代码实现 3.1 PWM.c 3.2 PWM.h 3.3 Servo.c 3.4 Servo.h 3.5 main.c 3.6 完整工程文件 PWM和OC输出详解&#xff1a; STM32定时器的OC比较和PWM​​​​​​​ 1. …

如果把软路由的网段更换成169.254.0.0/16会咋样?

前言 这几天有小伙伴在折腾软路由系统&#xff0c;然后问题就来了。 他咨询的是&#xff1a;为啥电脑连接软路由之后&#xff0c;无法访问软路由的管理页&#xff1f; 嗯。。。确实不是什么大事。但不注意看&#xff0c;还以为软路由没有正常获取到ip。 熟悉网络的小伙伴们都…