java 设计模式
设计模式
诗水人间
要想走的更远,就需要思考更深层次的问题。冷静、智慧、深沉是我所向往的
展开
-
UML类图之间箭头所表示的含义
为了学好设计模式需要看懂UML类图(帮助我们更好的理解类之间的关系)类与类之间的关系有6种,如下图是我制作好的接口关系,以及对应代码的关系。注意:关联关系是用实线表示的,下面的第二个实际上应该是实线而不是箭头,但是亿图中却用这种箭头表示关联(个人也觉得比较合理)1、依赖关系(只要A用到了B,A和B就存在依赖关系)依赖的范围比较广,类与类之间是肯定存在依赖关系的,如果不存在那么就没必要研究,因此解耦只能说尽可能的解耦,如果解耦到两个类完全没有关系那么就没有必要研究。2、关联关系(1对多等关系就是关原创 2021-04-08 02:35:55 · 1807 阅读 · 0 评论 -
java设计模式系列的7大设计原则
一、单一职责原则(拆分责任)二、接口隔离原则(最小接口隔离原则)三、依赖倒转原则(面向接口编程)四、里氏替换原则(尽量不重写父类方法):可以通过增加基本类让原来的子类和原来的父类通过聚合、组合、依赖关系来降低耦合性五、开闭原则 (英文OCP,新增功能不能影响原先功能)六、迪米特法则(最小知道原则:只与直接朋友交流)七、合成复用原则(使用合成进行解耦)...原创 2019-11-08 15:18:05 · 130167 阅读 · 3 评论 -
(行为型)20、解释器模式(解释某个表达式,表达式则是根据某种规则定义的)
解释器模式给分析对象定义一个语言,并定义语言的文法表示,再设计一个解释器来解释语言中的句子。包含的角色抽象表达式:约定一个规则(定义解释器接口,约定解释操作)终结符表达式:表达式的终结条件(解释的终止条件)非终结符表达式:环境:客户端:解释器模式在生活中很常见,举一个旅游场景例子。抽象规则:在生活中我们经常会定义一些规则,在旅游的场景中假设我们定义了免费开放的人群:老人、孩子、医生,免费开放的城市:武汉、上海某某游乐园。/** * 身份信息表达式 * 表达式的解析 *原创 2021-08-15 16:36:56 · 252 阅读 · 0 评论 -
(行为型)19、备忘录模式(保存状态,方便后面恢复。与快照的概念相同)
备忘录模式简单的理解为保存恢复,像游戏里的存档,需要的时候再进行读档。官方的解释:再不破坏封装性的前提下,捕捉一个对象的内部状态,并再该对象之外保存这个状态,以便以后需要时将该对象恢复到原先保存的状态。该模式又叫快照模式在备忘录模式中有3种角色:发起人:记录当前时刻的内部状态信息备忘录:负责存储发起人的内部状态管理者:对备忘录进行管理,提供保存和查看备忘录的功能,不可以进行 访问和修改 备忘录。发起人发起人拥有基本的属性信息,同时需要能调用管理者进行状态保存。/** * 角色:发原创 2021-08-15 15:12:17 · 263 阅读 · 1 评论 -
(行为型)18、观察者模式(状态变化后进行通知操作,相当于发生某个动作后会触发另外一个动作)
观察者模式定义对象间的一对多依赖,当一个对象状态变化时,相关的依赖对象都得到通知并被自动更新。别名:发布-订阅模式、模型-视图模式、源-监听器模式、从属者模式。举一个观察者模式的例子:在前端使用Vue写程序时,都对Vue的数据绑定表示肯定。那么在日常开发过程中肯定存在一个对象绑定多个标签,然后当数据变化时对应着行为或者数据也都发生变化。Vue只需要收集绑定了同一个数据的所有元素。然后我们通过维护这一个集合,当数据变化时,通过遍历进行处理,那么就可以实现多个标签上的数据渲染。而观察者模式的原理就原创 2021-08-09 01:17:44 · 264 阅读 · 2 评论 -
(行为型)17、中介者模式(所有人都找中介联系)
中介者模式网状关系变化为星状关系例如有一个飞机厂,假设跑道只有一条,那么不同的飞机要使用跑道他们之间需要互相通知,最终确定哪一个飞机使用跑道,相当于需要形成网状的通讯而有了中介者后不同的飞机只需要和这个中介者进行通信即可,于是也就诞生了塔台中介者/** * 塔台:中介者 * * 网状变为星状 */public class ControlTower { private boolean canDo = true; //接受请求... public void原创 2021-07-27 22:41:59 · 241 阅读 · 0 评论 -
(行为型)16、状态模式(不同的状态对应不同的功能,状态会动态循环变化,而策略模式则是不会循环变化)
状态模式状态模式拥有切换状态的功能(状态的流转)第一步、抽象状态:/** * 抽象状态 */public interface TeamState { //玩游戏 void playGame(); //切换到下一个状态 TeamState next();}第二步、定义具体的状态实现和状态的流转1、休假状态/** * 休假状态 */public class VocationState implements TeamState { @原创 2021-07-27 22:32:19 · 265 阅读 · 0 评论 -
(行为型)15、策略模式(不同的分支代表不同的策略)
策略模式方法存在不同的实现,将不同的实现抽取出来通过策略来进行调用。需要什么策略就调用对应的方法实现可以参考之前写过的一篇文章:策略模式的妙用(java8中 lambda表达式的灵活使用)常常我会将策略模式与HashMap一起使用,因为HashMap的get方法得到的就是不同的策略。然后调用这个策略的具体方法即可实现不同策略的调用。策略模式的好处在于不同的功能只需要通过同一个策略进行调用而不需要将所有功能写在一个方法中,代码阅读性差且容易出bug...原创 2021-07-27 22:16:36 · 273 阅读 · 0 评论 -
(行为型)14、模板方法模式(父类定义抽象算法,可以部分实现,子类进行不同的实现)
模板模式举一个炒菜的例子,炒菜的过程是一致的,但是我们可以炒出不同的才,只需要将不同的菜放入锅里炒即可,加盐的量也是变化的。故炒菜的模板可以这样设计父类/** * 1、定义炒菜模板 */public abstract class CookTemplate { /** * 定义算法: 定义好了模板,炒菜的过程是一致的故将这一个写好 * 父类实现某些步骤 * 子类实现具体的方法 */ public void cook(){原创 2021-07-27 22:03:58 · 271 阅读 · 0 评论 -
(结构型)13、享元模式(共享公用的对象)
享元模式享元模式与原型模式返回的对象的区别:享元返回的是对象本身,二原型模式返回的是克隆体享元模式:运用共享技术,有效地支持大量细粒度对象的复用。内部状态:可以共享的相同内容外部状态:不能共享的内容在享元模式中通常需要配合工厂模式,需要创建一个享元工厂来负责维护一个享元池用于存储具有相同内部状态的享元对象。举一个享元模式的例子服务员:不同的服务员有相同的属性:工号、名字、年龄;但是这些服务员提供的是不同的服务import lombok.AllArgsConstructor;/*原创 2021-07-27 21:40:48 · 296 阅读 · 0 评论 -
(结构型)12、组合模式(部分即整体)
组合模式组合模式在定义类的时候就算是组合了,几乎无处不在,组合模式可以组合单一对象,也可以组合不同对象在设计模式的总则中有一句话:“少用继承,多用组合、聚合的方式实现解耦”单一对象:class Meau{ private int id; private String name; List<Meau> meaus;// 组合自己}不同对象:其中的age和name也算是组合,所以说组合模式无处不在class Person{ private int age; private原创 2021-07-27 21:22:30 · 218 阅读 · 0 评论 -
(结构型)11、外观模式(组合的方式封装多个功能)
外观模式外观模式:将高频使用的功能封装为一个功能(一个外观多个功能)简单的理解就是封装多个功能伪代码class FacadePattern{ //功能一 //功能二 //功能三 void doSomething(){ // 功能一 // 功能二 // 功能三 }}参考文章:https://www.jianshu.com/p/b9dd384d14a8...原创 2021-07-24 00:57:39 · 196 阅读 · 0 评论 -
(结构型)10、代理模式(通过中介达到效果)
代理模式代理模式分为静态代理 和 动态代理代理模式可以简单的理解为中介,意思就是实现一个功能我们不直接使用原对象调用,而是使用代理类进行调用,而代理类最终会调用被代理对象的功能。静态代理(等同于装饰器模式)静态代理:就是代码写死需要被代理那个对象。缺点:代理的对象不一样,就需要创建不同的代理类。动态代理动态代理:在程序运行时才确定代理那个代理对象。动态代理分两种:jdk动态代理:使用java多态的方式实现cglib代理:使用字节码增强器实现在使用springboot的过程中我相信原创 2021-07-23 02:22:15 · 237 阅读 · 0 评论 -
(结构型)9、装饰器模式(在不改变原对象的前提下给已有对象添加新功能)
装饰器模式装饰器模式和代理模式非常的相似。装饰器的作用是额外的添加一些功能,而代理模式侧重于原方法的调用过程(常常用于AOP)。可以和代理模式进行类比,相当于调用某些功能添加一些额外的功能。在实际使用过程中其实和代理模式非常的相似/** * 核心:想要不改变原来接口方法的情况下扩展新功能,或者增强方法..... */public class MainTest { public static void main(String[] args) { //1、得到原对象。原创 2021-07-22 14:03:47 · 349 阅读 · 1 评论 -
(结构型)8、桥接模式(抽取抽象相同的因素,将多个抽象进行组合实现桥接模式)
桥接模式出现多维度因素时我们可能会产生很多类。如果你来定义下面的类来表示下面的4种手机怎么定义呢?手机类型\渠道线上线下…小米手机华为手机…如果后面 手机类型 和 渠道 需要进行新增会影响现有代码?将维度抽象抽取,利用桥接模式(组合)可以使维度进行横向扩展(对销售类型进行扩展)...原创 2021-07-22 13:29:40 · 210 阅读 · 0 评论 -
(结构型)7、适配器模式(转换一个接口为客户端想要的另一个接口)
结构型之所以称为结构型设计模式,是这类设计模式通过定义类结构实现功能。如后面的 MovieAdapter 类的定义适配器模式不改变原有接口和类,新增抽象将其组合实现适配举个例子:①放一部带中文字幕的英语电影。我们需要实现一个带英语翻译器的电影播放器。②如果放一部带英文字幕的中文电影。那么就需要实现一个带中文翻译器的电影播放器如果使用适配器来实现这个功能来实现上面类似的场景那么可以和下面一样进行定义即可。然后原先使用的是上面对应的①②等对应的播放器,现在我们只需要使用适配器进行放电影即可原创 2021-07-21 15:23:56 · 469 阅读 · 0 评论 -
(创建型)6、建造者模式(具体的原料由我们提供,怎么创建对象的可以不知道)
建造者模式应用场景:StringBuilderSwagger-Builderlombok的@Builder注解快速实现建造者模式编码规范:程序中用到了什么模式就 XXX设计模式 ,例如StringBuilder、BeanFactory一、定义建造者以建造一个手机为例1、实体手机public class Phone { protected String cpu; protected String memory; protected String disk;原创 2021-04-19 15:33:02 · 212 阅读 · 0 评论 -
(创建型)5、抽象工厂模式(定义顶级抽象,然后细化抽象,最后具体工厂进行创建对象)
抽象工厂模式前面讲了:简单工厂 —> 工厂模式 它们一个个过度,依然存在缺陷。建议先从简单工厂开始看,然后一级一级到抽象工厂。下面是抽象工厂的整体设计,对于后面步骤完整后的整体关系图如下抽象工厂要做的事情一、定义顶级抽象(总的规则)前面谈到,如果我们要创建各自不同类型的产品,那么工厂模式和简单工厂模式就不好用了。例如:我们需要创建 跑车、货车、N95口罩、普通口罩…依此类推。如果使用简单工厂那么结果就是违反开闭原则,需要直接修改简单工厂源码,新增很多if-else,如果换成工厂方法,原创 2021-04-19 03:18:14 · 362 阅读 · 0 评论 -
(创建型)4、工厂模式-----(通过抽象工厂的抽象方法 的子类工厂 实现创建对象,通过增加工厂达到扩展开放,修改关闭原则)
工厂模式简单工厂存在if-else分支过多,违反开闭原则,扩展不易,因此为了进行解耦,可以通过抽象工厂来避免写if-else,通过增加抽象工厂来实现创建对应我们想要的对象。工厂模式的关系图如下原来简单工厂我们会这样定义一、定义抽象车public abstract class AbstractCar { String engine;// 定义引擎 public abstract void run();// 定义运行方式}二、定义具体的车,继承抽象车产品1、跑车publi原创 2021-04-19 01:34:06 · 282 阅读 · 0 评论 -
(创建型)3、简单工厂模式(通过if-else 然后直接new 对象返回)
简单工厂模式简单工厂模式:需要什么就从简单工厂中获取(让简单工厂帮你new对象)将需要的传入,然后简单工厂就创建好了一个对象给我们。传入什么一般可以通过if-else就可以做到拆分,有些时候也可以使用枚举abstract class Fruit{ private String name;}class Apple extends Fruit{ }class Orange extends Fruit{ } /** * 简单工厂示例 */class FruitSampleFact原创 2021-04-18 23:00:44 · 299 阅读 · 0 评论 -
(创建型)2、原型模式(返回原对象的克隆体,不直接返回原对象)
原型模式在JDK 中对应的就是 Cloneable接口。如果一个对象想要调用clone方法(Object中有定义)得到一个对象的克隆体,需要实现Cloneable接口。否则会报java.lang.CloneNotSupportedException。为什么需要使用原型模式?在解决这个问题前我们需要了解原型模式的应用场景,从其名称就能知道大概什么意思,原型就是需要有一个原来对象,目的就是为了得到一个克隆对象。为什么要这样做呢?在我们开发的过程中经常会遇到对象多次被重复利用,如果我们每一次去利用一个对原创 2021-04-18 22:34:23 · 407 阅读 · 0 评论 -
(创建型)1、单例设计模式以及使用场景
单例模式的使用场景例如:数据源、session工厂需要频繁的创建和销毁对象经常需要使用的对象创建的对象销毁过多的资源工具类对象饿汉式静态常量class Singleton { //1. 构造器私有化, 外部不能new获取 private Singleton() {} //2.本类内部创建对象实例 private final static Singleton instance = new Singleton(); //3. 提供一个公有的静态方法,返回实例对象原创 2020-06-11 00:20:42 · 139177 阅读 · 1 评论 -
类之间的6大关系
依赖关系判断A类和B类是否存在依赖关系A类中用到B类B类是A类的成员属性A类方法的返回类型是B类A类方法的参数类型是B类A类方法中使用到B类A类中用到类B泛化关系(继承extends)实现关系(实现implements)关联关系关联关系实际上就是类与类之间的联系,关联关系是特殊的依赖关系;关联关系存在导向型,例如:单向关联:单向引用public class A{ private B b;}public class B{}双向关联:互相引用public class原创 2020-06-10 02:59:57 · 128047 阅读 · 0 评论 -
合成复用原则
继承的方式偶合性很强例如如下代码class A{ public void method1(){} public void method2(){}}class B extends A{ }先A类需要添加一个新方法method3(),但是B类用不到,如果用继承的方式去调用,那么method3也会被B继承;很明显偶合性高。使用 合成/聚合/组合方式降低偶合合成class A{ public void method1(){} public void method2(){}}clas原创 2020-06-10 02:27:39 · 146049 阅读 · 0 评论 -
迪米特法则(最少知道原则,只与直接朋友交流,降低类之间的偶合)
有两个类 A类 B类下面情况属于直接朋友的关系:B是A的 成员变量B是A中 方法的参数A的 方法返回值是B类型成员变量属于直接朋友。如下class A{ private B b;}方法中的参数class A{ public void hello(B b){ }}方法的返回类型class A{ public B hello(){ }}陌生的类关系举例:陌生的类相当于工具类,好比B是A的工具类,只是在方法中用到类一下class A{ public hello()原创 2020-06-10 01:57:47 · 112624 阅读 · 0 评论 -
开闭原则(增加新功能时、不会影响到原来的使用方式)用抽象构建框架、用实践扩展细节
基本概念开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则 一个软件实体如类,模块和函数应该对扩展开放(对提供方,工具类即被调用者),对修改关闭(对使用方即调用者)。用抽象构建框架,用实现扩展细节。 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则...原创 2019-11-30 03:29:01 · 154414 阅读 · 0 评论 -
里氏替换原则(尽量不重写父类方法 通过增加基类 让原 子类和原 父类 通过聚合、组合、依赖关系来降低耦合)
基本概念:里氏替换原则是 麻省理工大学一位姓里的女生在1988年提出的 在继承时,子类中尽量不要去重写父类方法 (举例:A类的所有方法都被B类重写了。 那何必继承呢?直接新建一个B类不就好了) 里氏替换原则告诉我们,继承让两个类耦合性增强了,在适当的情况下通过聚合、组合、依赖来解决问题里氏替换要做的事: 增加基类,降低耦合性举例:public class ...原创 2019-11-09 04:08:22 · 132258 阅读 · 0 评论 -
依赖倒转原则 (面向接口编程)
基本概念:高层模块不应该依赖低层模块,二者都应该依赖其抽象 抽象不应该依赖细节(具体实现),细节(具体实现)应该依赖抽象 依赖倒转(倒置)的中心思想是面向接口编程 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。 以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类 使用接口或抽象类的目的是制定...原创 2019-11-09 03:19:58 · 137653 阅读 · 0 评论 -
接口隔离原则(最小接口隔离原则)
基本概念: 接口实现类不应该依赖它不需要的接口,即要保证最小接口原则。接口隔离要做的事: 如果一个类通过一个接口的实现类,只使用了部分方法,则应当将接口拆分(按照最小接口原则)拆成多个接口举例:如下有一个接口 Interface1 有5个抽象方法,其中B、D都是Interface1的实现类而A需要使用B实现的operation1-3方法,C则需要使...原创 2019-11-09 01:47:29 · 147921 阅读 · 0 评论 -
单一职责原则(拆分职责)
基本概念: 对于一个类来说一个类应该只负责一项职责。单一职责要做的事:降低类的复杂度,一个类只负责一项职责 提高类的可读性,可维护性 降低变更引起的风险另外注意: 当逻辑足够简单时,才可以在代码级别违反单一职责原则; 当类中方法数量足够少,可以在方法级别上保持单一职责原则,否则当准守类单一职责原则(将职责拆分为多个类)举例:主...原创 2019-11-08 21:56:36 · 131519 阅读 · 0 评论