设计模式学习记录

news2025/1/17 21:43:29

设计模式

UML图:

------> 依赖

——>关联

-------▲ 实现

—–—▲ 继承

🔺———> 聚合

▲———> 组合(关联性更强)

一、策略模式(行为型)

策略模式:是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同。

策略模式的Strategy类层次为Context定义了一系列的可供重用的算法和行为。在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式Context对象

二、单一职责

对于一个类来说,应该仅有一个引起它变化的原因。

将一个应用的功能剥离开(例如:视图和业务逻辑),否则将这些职责耦合在一起,会导致这个应用很脆弱。耦合性高,代码复用性低。

比如:俄罗斯方块游戏:可以分为界面窗体类+游戏逻辑类(旋转、移动、下落、堆积)

三、开闭原则

对于软件实体来说,应该可以对外扩展,但是不可修改。

在我们最初编写代码时,假设变化不会发生。

当变化发生时,我们就创建抽象(接口、抽象类)来隔离发生的同类变化。

四、依赖倒转原则

对于一个系统来说,每个部分的功能应该独立且单一,当出问题了只需要修改相应的部分即可(单一职责原则),并且应该尽量做到对外扩展开发,对外修改关闭。(开闭原则)。每个部分之间可以做到轻松的组合起来(依赖倒转原则,面向抽象编程(接口))

在应用中不应该高层模块依赖底层模块,容易出现底层模块发生变化,高层也要变化。所以,无论是高层还是底层都应该依赖于接口,这样如果接口稳定,就不用担心其他模块受到影响。

五、里氏替换原则

一个软件实体如果使用的是一个父类的话,那么一定是用于它的子类,而且察觉不出来区别。

任何父类出现的地方都可以用子类代替。

由于子类型的可替换性,才使得使用夫类型的模块在无需修改的情况下可以扩展。

六、装饰器模式(结构型)

装饰器模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。在这里插入图片描述

代码实现:

Component:

abstract class Component {
	public abstract void Operation();
}

ConcreteComponent(真实对象)

class concreteComponent extends Component {
	public override void Operation (){
		Console.WriteLine("具体的对象操作");
	}
}

Decorator(对原对象进行扩展)

abstract class Decorator extends Component {
	protected Compoment compoment;
    public void setCompoment(Compoment compoment) {
        this.compoment = compoment;
    }

    @Override
    public void Operation() {
        if(compoment != null) {
            compoment.Operation();
        }
    }
}

ConcreteDecoratorA(具体的装饰对象)

public class ConcreteDecoratorA extends Decorator{
    private String strA = "A的功能扩展";

    @Override
    public void Operation() {
        compoment.Operation();
        strA = "A";
        System.out.println("装饰者A的装饰");
    }
}

ConcreteDecoratorB(具体的装饰对象)

public class ConcreteDecoratorB extends Decorator{
    @Override
    public void Operation() {

        compoment.Operation();
        actionByB();
        System.out.println("装饰者B的装饰");
    }
    public void actionByB() {
        System.out.println("装饰者B特有的行为");
    }
}

客户端代码:

public class Main {
    public static void main(String[] args) {
        Compoment p = new ConcreteComponent();       //创建一个具体对象
        ConcreteDecoratorA cona = new ConcreteDecoratorA();    //装饰者A
        cona.setCompoment(p);                        //设置装饰的对象
        ConcreteDecoratorB conb = new ConcreteDecoratorB();   //装饰者B
        conb.setCompoment(cona);                     //设置装饰的对象
        conb.Operation();                               
    }
}

小节:

装饰模式是为已有的功能动态地添加更多功能的一种方式,把每个要装饰的功能放在单独的类中,并让这个类包装它要装饰的对象。因此,客户代码就可以在运行时根据需要有选择地、按顺序的使用装饰功能包装对象。

七、代理模式(结构型)

为其他对象提供一种代理以控制对这个对象的访问。一般使用的场合:远程代理(反向代理)、虚拟代理(存放实例化需要很长时间的真实对象)、安全代理(用来控制真实对象访问时的权限)。

在这里插入图片描述

代码实现:

公用接口

abstract class Subject {
   public astract void Request();
}

真实实体类:

class RealSubject extends Subject {
   public override void Request() {
      Console.WriteLine("真实的请求");
   }
}

代理类:

class Proxy extends Subject {
   RealSubject realSubject;
   public override void Request() {
      if(realSubject == null) {
         realSubject = new RealSubject();
      }
      realSubject.Request();
   }
}

客户端代码:

public static void main (String[] args) {
   Proxy proxy = new Proxy();
   proxy.Request();
   Console.Read();
}

装饰器模式和代理模式的区别:

  • 装饰器模式强调的时增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能。而代理模式强调要让别人帮你去做一些本身于你业务没有太多的关系的职责(日志处理、设置缓存),将核心业务和边缘业务分离开,降低程序的耦合度。
  • 装饰模式是以对客户端透明的方式扩展对象的功能;代理模式则是给一个对象提供一个代理对象,由代理对象来控制对象对原有对象的使用。
  • 装饰器模式的功能由客户端根据需求进行选择,更灵活,而代理模式的功能已经写死了
  • 代理注重对原对象的控制(代理模式中目标对象的生命周期是代理对象控制的),不易于二次扩展。装饰器通过上层装饰,易于扩展。

八、工厂方法模式(创建型)

//1、简单工厂的结构、缺点

如果我们要设计一个代码复用性高、扩展性高(开闭原则),并且基于依赖反转以及单一职责原则我们可以实现一个基类(运算抽象类),然后分别具体的加法类、减法类等重写运算类。最后实现一个简单工厂类,可以根据不同的规则创建不同的对象。

但是,当我们要新增一个开根运算运算时,我们需要继承运算类,然后重写方法,最后修改工厂类逻辑,此处破坏了开闭原则,导致程序的耦合度过高。所以我们引入了工厂方法模式

在这里插入图片描述

​ 简单工厂类结构图

//2、简单工厂模式和策略模式的区别

简单工厂模式和策略模式的区别:
  1. 用途不一样,简单工厂类是创建型模式,它的作用是创建对象。策略模式是行为型模式,作用是在许多行为中选择一种行为,关注的是行为的多样性。
  2. 解决的问题不同。简单工厂模式是解决资源的统一分发,将对象的创建分离开。策略模式解决的是策略的切换和扩展。

==重点:==如果在适用策略模式的地方使用简单工厂模式,如果新增加策略就要修改工厂类,而这个可能会导致其他错误,也破坏了开闭原则。如果使用了策略模式,只要将新增加的策略当作参数传递到Context类中即可。

//3、工厂方法模式的结构、优点

于是工厂方法模式来了,直接看结构图:

在这里插入图片描述

​ 工厂方法模式结构图

根据上图可以看出,工厂方法模式多了具体运算类的工厂类,所以当我们要新增运算,我们的步骤是:

  1. 编写具体类实现运算类重写运算方法.
  2. 实现自己的工厂类实现抽象工厂类。
  3. 根据需要,在客户端选择合适的工厂创建不同的运算对象。

所以工厂方法模式解决了简单工厂破坏了开闭原则的缺点。

九、原型模式(创建型)

用原型实例指定创建对象的种类,并通过这些原型实例创建新的对象。

一句话就是通过clone()克隆在特定场景下代替new创建对象。

  • 不需要知道任何细节的情况下,从一个对象创建另一个可定制对象。
  • new消耗的代价大。

值得注意的是有深拷贝浅拷贝

十、模板方法模式(行为型)

定义一个操作中的算法的框架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义改算法的某些步骤。

当子类出现相同的逻辑,我们可以将这些不变的逻辑提取放在超类中去实现。通过父类中定义抽象方法,在不同子类之间实现这个方法来实现可变的逻辑。

十一、迪米特法则

也叫最少知识原则,如果两个类不必直接通信,那这两个类不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

每一个类都应当尽量降低成员的访问权限,迪米特法则强调类之间的松耦合,类之间的耦合越弱越容易被复用。

十二、外观模式(结构型)

为子系统的一组接口(股票)提供一个一致的界面(基金),此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

也就是定义一个中间类(外观),对所要使用的类进行封装,之后可以直接调用这个中间类(外观)就行了。

外观模式体现了依赖倒转、迪米特法则

结构图:

在这里插入图片描述

何时使用外观模式:

  • 首先,设计初期,有意识地将不同的两个层分离,层与层之间建立外观类
  • 其次,在开发阶段,子系统可能越来越复杂,增加外观类,减少他们的依赖。
  • 第三、维护遗留的大型系统时(很难维护、扩展),可以新增外观类对老系统进行屏蔽,之后新系统可以基于外观类进行开发。

十二、建造者模式(建造型)

//1、建造者模式是什么?

建造者模式:将一个复杂对象的构建(人的构建:头、胳膊、腿)和它的表示分离,使得同样的构建过程可以创建不同的表示。

//2、为什么要有建造者模式

用了建造者模式后,用户只需指定需要建造的类型就可以得到它们,而具体的建造过程和细节就不需要知道。

//3、建造者模式的结构
在这里插入图片描述

  • Builder : 建造者的抽象类
  • ConcreateBuilder : 实现Builder接口,具备创建能力,时具体的建造者。
  • Product:具体的实体(人)
  • Director: 指挥者,根据用户的需求构建Product,传入不同的Builder对象,建造不同的实体

//4、什么时候需要使用建造者模式呢?

主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。

十三、观察者模式(行为型)

//1、特点

又叫发布-订阅模式。定义了一种一对多的依赖关系(同事依赖前台小姐姐盯住老板),让多个观察者对象同时监听某一个主题对象。这个主题对象状态变化时,会通知所有观察者模对象,是他们能够自动更新自己。

//2、结构

在这里插入图片描述

//3、使用

应用场景:当一个对象的改变需要同时改变其他对象的时候,而且不需要知道有多少对象待改变时。

观察者模式所做的工作就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖具体,从而使得各自的变化都不会影响另一边的变化。

但是:抽象通知者还是依赖抽象观察类,并且不同的观察者针对通知者的变化可能有不同的行为,所以可以去掉抽象观察类,使用委托方法来优化。

  • 委托可以搭载多个方法,我们可以像调用方法一样调用委托,所有的方法都会被唤起,这些方法不需要属于同一个类。但是所搭载的方法必须具有相同的原型(形参、返回值)

十四、抽象工厂模式(建造型 )

抽象工厂模式和工厂方法模式很类似,提供一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

具体的工厂类中有多个产品的createxxx()方法(Iuser、Idepart)。

优缺点:

优点:

  • 将具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离。

缺点:

  • 当需要添加新需求的时候(product),需要新增三个类(IProduct、具体的实现),以及修改工厂类。

在这里插入图片描述

改进:

去除工厂类,新增DataAccess类,根据String db = ‘’xxx‘’,通过case “不同数据库” 创建不同的实例。

但是我们可以使用反射去优化,并通过配置文件,将使用的具体的数据库赋值给db。

十五、状态模式

当控制一个对象状态装换的条件表达式过于复杂时,把状态的判断逻辑转移到表示不同状态的一系列类中。通过把各种状态转换逻辑分布到State的子类之间,来减少相互之间的依赖。

何时使用状态模式:

当一个对象的行为取决于他的状态,并且他必须在运行时刻根据状态改变它的行为时。

十六、适配器模式

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

分为类适配器对象适配器

类适配器UML结构图:

在这里插入图片描述

通过继承原有类、实现目标接口来实现适配。

对象适配器UML结构图:

在这里插入图片描述

继承原有类、关联目标对象(类似代理)。

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

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

相关文章

Java --- Spring6项目创建及注意事项

目录 一、Spring框架解决的问题 二、Spring介绍 三、Spring八大模块 四、Spring特点 五、第一个Spring6入门程序 六、spring的细节 6.1、配置文件的bean的id不能重复 6.2、spring底层是通过反射调用无参构造方法创建对象 6.3、spring会把创建好的对象存储在Map集合中 6.4…

【数据结构初阶】树+二叉树+堆的实现

真正的勇士,就是在看清生活的真相后,依旧慷慨面对他所遭受的苦难与挫折。 大学究竟教会了我们什么呢?或许答案只有一个,看清自己,与自己和解,和自己坐下来谈一谈。 人生或许本就没有什么意义,…

MySQL的缓冲池(buffer pool)及 LRU算法

1.什么是缓冲池(buffer pool) buffer pool 是数据库的一个内存组件,里面缓存了磁盘上的真实数据,Java系统对数据库的增删改操作,主要是这个内存数据结构中的缓存数据执行的。 控制块 存的是 数据页所属的表 空间号&a…

MATLAB break语句

MATLAB中 break 语句用于终止 for 或 while 循环的执行,当在循环体内执行到该语句的时候,程序将会跳出循环,继续执行循环语句的下一语句。 注意:在嵌套循环中,break 退出只能在循环发生,后通过的声明控制循…

git关于创建/删除分支常用命令

主要用来介绍git中如何操作分支的命令&#xff1a; 1.git查看所有的分支: git branch -a 2.创建本地分支&#xff1a; git checkout -b <name> 3.有了本地分支之后推送到远程分支; git push origin <name> 4.切换分支&#xff1a; git checkout <name> 5.删除…

黑*头条_第5章_文章发布粉丝管理成形记

黑*头条_第5章_文章发布&粉丝管理成形记 文章目录黑*头条_第5章_文章发布&粉丝管理成形记文章发布&粉丝管理1 需求分析1.1 功能需求1.2 前端需求1.2.1 图文数据需求1.2.2 素材管理需求1.2.3 发布文章需求1.2.4 内容列表需求1.2.5 粉丝概况需求2 定义2.1 后端定义2.…

MacBook磁盘内存空间清理软件CleanMyMac2023

Mac电脑用的时间久了&#xff0c;Mac用户尤其是MacBook用户会经常收到“磁盘几乎已满”的提示&#xff0c;如何解决这个问题&#xff0c;当我们使用苹果MAC一段时间后&#xff0c;就会有大量的垃圾文件占用磁盘空间&#xff0c;例如系统缓存文件、应用程序缓存文件、备份和重复…

2022/11/18[指针] 关于指针的初步理解

先看一段利用指针交换a和b值得代码&#xff1a; #include<stdio.h> void swap(int* p1, int* p2); int main() {int a, b;int* pa, * pb;printf("enter:");scanf_s("%d%d", &a, &b);pa &a;pb &b;printf("%d,%d\n", pa,…

面试:线程池核心线程如何保持一直运行的

对于Java中 Thread 对象&#xff0c;同一个线程对象调用 start 方法后&#xff0c;会在执行完run 后走向终止&#xff08;TERMINATED&#xff09;状态&#xff0c;也就是说一个线程对象是不可以通过多次调用 start 方法重复执行 run 方法内容的。Java的线程是不允许启动两次的&…

frp内网穿透服务

参考博客&#xff1a; https://www.jianshu.com/p/19ea81efffc4 https://blog.csdn.net/yj222333/article/details/124752420 依赖于&#xff1a;Github开源软件FRP 下载地址&#xff1a;https://github.com/fatedier/frp/releases frp 主要由 客户端(frpc) 和 服务端(frps…

基于JAVA景区售票系统设计与实现 开题报告

本科生毕业论文 基于java框架springboot旅游景区景点购票系统 开题报告 学 院&#xff1a; 专 业&#xff1a; 计算机科学与技术 年 级&#xff1a; 学生姓名&#xff1a; 指导教师…

三维模型文件以及obj、ply格式文件生成pcd点云文件

方法一、三维模型文件生成obj文件 要想生成点云文件&#xff0c;要先将三维模型文件保存为obj文件格式&#xff0c;步骤如下&#xff1a; 通过SolidWorks将模型保存为stl文件格式打开SolidWorks的插件选择&#xff0c;在ScanTo3D前面打勾 在solidworks中以网格文件的形式打开…

通信算法之九十六:电力通信系统-HRF多载波通信系统-物理层收发信道开发

目录1.HRF通信系统-物理层收发信道开发1.1 SIG发射机算法功能模块1.2 SIG接收机算法功能模块1.3 PHR发射机算法功能模块1.4 PHR接收机算法功能模块1.5 PSDU发射接收机处理流程1.6前导LTF/STF序列发射接收处理流程1.7PPDU帧&#xff08;前导SIGPHRPSDU&#xff09;发射接收处理流…

阿里云服务器(Ubuntu)配置nextcloud个人网盘

tags: Ubuntu Server Linux 写在前面 最近迷恋上了云服务器的配置, 感觉云服务器能做的事情太多了, 不管是docker还是直接部署, 都是相当方便快捷的, 下面来看看在阿里云服务器配置nextcloud网盘的基本配置方法, 这里参考了一篇文章1, 写的相当详细了, 我这里只是做一些补充.…

【5G MAC】Msg1 TX开环功控介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

使用python编写mqtt客户端向EMQX服务器发送数据

摘要&#xff1a;本文介绍如何用python编写一个mqtt客户端向EMQX服务器发送数据&#xff0c;实现一个简易的本地物联网服务器。 上一篇文章讲到使用mqtt.fx软件来发布消息。 (1条消息) 使用mqtt.fx向EMQX服务器发送消息_TMS320VC5257H的博客-CSDN博客https://blog.csdn.net/yo…

【树莓派不吃灰】命令篇⑦ 学习awk命令

目录awk 命令1. 基本语法2. 工作原理3. 基础实例操作3.1 把用户名和Shell打印出来3.2 找到以ssh关键字开头的所有行&#xff0c;并输出用户名和shell&#xff0c;中间以“-”分割3.3 给用户 ID加上一个常量3.4 输出第一个字段为sshd所在的行4. BEGIN END 操作4.1 基于3.2&#…

智慧仓储解决方案-最新全套文件

智慧仓储解决方案-最新全套文件一、建设背景二、思路架构三、建设方案四、获取 - 智慧仓储全套最新解决方案合集一、建设背景 仓储行业目前存在的问题 仓管员需要手动录单&#xff0c;工作量大&#xff0c;易出错&#xff0c;无法保证数据的准确率和及时性。 批次属性复杂、保…

计算机里的刻度:时钟和步进器

计算机的底层逻辑很简单&#xff0c;它们被定义为完成一些简单的事情。计算机是一个复杂系统&#xff0c;复杂的是如何规划好处理这些简单的事情的时间和步骤。本节就可以了解到计算机的时间刻度和步进器的构成&#xff0c;帮助我们进一步理解计算机的底层工作原理。 时钟是什…

redis三(3-1)

分布式缓存 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题 一、redis持久化 - RDB持久化 - AOF持久化1.1RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xff0c;也被叫做Redis数据快照。简单来说就是把内存中的…