# java_design_mode4 **Repository Path**: ran7x/java_design_mode4 ## Basic Information - **Project Name**: java_design_mode4 - **Description**: Java常用设计模式(全23种) - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-06-11 - **Last Updated**: 2024-07-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # java_design_mode Java设计模式 ## 前言 Java设计模式的学习,代码详解等。 参考视频:https://www.bilibili.com/video/BV1af4y1y7sS https://www.runoob.com/design-pattern/design-pattern-intro.html http://c.biancheng.net/view/1366.html 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。 这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 ## 参考书籍 设计模式相关的书籍我收集了一下,放在resources/static/pdf文件夹下。包括: [大话设计模式](src/main/resources/static/pdf/大话设计模式(程杰).pdf) [重学Java设计模式](src/main/resources/static/pdf/重学Java设计模式(付政委).pdf) [秒懂设计模式](src/main/resources/static/pdf/秒懂设计模式(刘韬).pdf) [图解设计模式](src/main/resources/static/pdf/图解设计模式(结城浩,杨文轩).pdf) ## 包目录说明 ### 1 singleton 单例模式 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 * 饿汉式 * 懒汉式 * 普通加锁模式 * 双重检查锁模式 > 单例模式的重点是 构造函数私有化,同时提供一个静态方法对外提供单一的实例化对象。 ### 2 simpleFactory 简单工厂模式 简单工厂模式又称为静态工厂方法模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。 ![1](src/main/resources/static/readmeImg/1.png) > 通过工厂实例,根据不同的传入参数来生成不同的实例化对象。 ### 3 factory 工厂方法模式 定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。 ![2](src/main/resources/static/readmeImg/2.png) ![3](src/main/resources/static/readmeImg/3.png) > 工厂方法模式是对简单工厂模式的进一步抽象化,通过工厂方法,根据不同的传入参数来生成不同的工厂实例,然后生成不同的产品对象。 > 工厂方法模式和简单工厂模式的区别在于,简单工厂模式是根据不同的传入参数生成不同的产品,而工厂方法模式则是根据不同的传入参数生成不同的简单工厂。 ### 4 abstractFactory 抽象工厂模式 ![4](src/main/resources/static/readmeImg/4.png) ![img.png](img.png) 抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。 但是还是需要修改抽象工厂和具体工厂的代码,违反开闭原则。 > 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产产品,而抽象工厂模式可构造工厂方法。 ### 对比: 简单工厂模式 工厂模式 抽象工厂模式 在Java中,工厂模式是一种常用的设计模式,主要用于封装对象的创建过程,提供一种请求其产品对象的统一接口,而无需指定具体的类。工厂模式主要有三种形式:简单工厂模式、工厂方法模式(通常简称工厂模式)和抽象工厂模式。下面我们以制作饮料为例,通俗易懂地对比这三种模式。 ### 1. 简单工厂模式 想象一下,你是一家饮品店的老板,店里售卖多种饮料,比如咖啡、茶和果汁。简单工厂模式就像是店里的一个大厨,他负责根据顾客的订单制作相应的饮料。顾客只需要告诉大厨他们想要什么,大厨就会为他们准备。 **优点**:客户只需知道“我要一杯咖啡”这样的需求,而不用关心咖啡是如何被制作出来的,即客户端与产品类解耦。 **缺点**:如果菜单上增加了新饮品(比如奶茶),那么大厨的职责就需要更新,即简单工厂类需要修改,这违反了开闭原则(对扩展开放,对修改关闭)。 ### 2. 工厂方法模式 现在,假设你的饮品店规模扩大,你开了多家连锁店。每家店都有一名大厨,但他们各自负责制作特定类型的饮品。比如,一家店的大厨专门做咖啡,另一家店的大厨专门做茶。这就相当于工厂方法模式,每家店(子类)都有自己的工厂(方法),负责生产特定类型的产品(饮料)。 **优点**:每种产品(饮料)都有对应的工厂(大厨),易于扩展新的产品(饮料),不需修改原有的工厂类。 **缺点**:产品种类增多时,工厂类也会增多,系统中类的数量会膨胀。 ### 3. 抽象工厂模式 随着业务进一步发展,你发现除了饮品,顾客还喜欢小食,比如蛋糕和饼干。于是,你决定在每家饮品店旁边开一家糕点店,每家糕点店都由一位糕点师负责制作所有类型的糕点。这时,每家饮品店和糕点店构成了一组产品系列,而每组产品系列都由各自的工厂负责生产。这就是抽象工厂模式。 **优点**:能够创建一系列相关或相互依赖的对象,而无需指定它们具体的类。 **缺点**:当产品族中增加新产品时,所有工厂类都需要进行修改。 **总的来说,简单工厂模式适用于产品种类较少,且后期不易扩展的场景;工厂方法模式适用于产品种类可能较多,且每种产品需要独立的创建逻辑的场景;抽象工厂模式适用于需要创建一组相关产品的情况,适用于产品族的创建。每种模式都有其适用场景,选择合适的模式可以提高代码的可维护性和扩展性。** ### 5 decorator 装饰器模式 动态地给一个对象添加额外的功能。就增加功能来说,装饰器模式比生成子类更加灵活。 ![5](src/main/resources/static/readmeImg/5.png) ![6](src/main/resources/static/readmeImg/6.png) ![7](src/main/resources/static/readmeImg/7.png) > 装饰器模式内部有一个原本的对象,重点在于将原本的方法还是交给原本的对象执行,只新增和修改新功能。 ### 6 adapter 适配器模式 适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。 ![8](src/main/resources/static/readmeImg/8.png) > 适配器模式是对一个对象方法进行封装,从而达到修改原有对象功能的意义。 ### 7 observer 观察者模式 观察者(Observer)模式指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。 ![9](src/main/resources/static/readmeImg/9.png) ![10](src/main/resources/static/readmeImg/10.png) > 观察者模式的重点在于内部维护一个依赖对象列表,同时依赖对象提供一个供被依赖对象操作的列表,方便调用。 ### 8 interview 外观模式 外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。 该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。 ![11](src/main/resources/static/readmeImg/11.png) ![12](src/main/resources/static/readmeImg/12.png) > 外观模式是通过一个外观类,外对提供一个整合所有操作的方法。 ### 9 status 状态模式 状态模式:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象,状态模式是一种对象行为型模式。 ![13](src/main/resources/static/readmeImg/13.png) > 状态模式的重点在于对象的操作会随着对象的状态的改变而变化,通过提供外对修改状态的方法。 ### 10 strategy 策略模式 策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。 策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。 ![14](src/main/resources/static/readmeImg/14.png) > 策略模式的重点在于对不同的操作进行分类,封装成算法。从而分割不同类型的操作。 > 策略模式和状态模式是比较相似的,它们的区别在于状态模式侧重于方法随着状态的改变而改变,而策略模式侧重于将不同的操作进行封装,方便替换。 ### 11 proxy 代理模式 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。 这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。 ![15](src/main/resources/static/readmeImg/15.png) > 代理模式侧重点在于控制原有对象不允许外部对象访问,只能通过指定代理访问。 > 代理模式、装饰器模式、适配器模式三者比较相似,都体现了对原有方法的封装。但装饰器模式侧重增加新功能,适配器模式侧重于改变原有功能,代理模式侧重于不允许外部访问原有功能。 ### 12 chainResp 责任链模式 责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起, 于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。 ![16](src/main/resources/static/readmeImg/16.png) > 责任链模式侧重点在于将前后的操作串联成链表,让请求沿着链表传递。 ### 13 templateMethod 模板方法模式 模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中, 使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。 ![17](src/main/resources/static/readmeImg/17.png) > 模板方法的重点是将父类的部分操作延迟到子类实现,子类则根据要求来做不同处理。 ### 14 flyWeight 享元模式 享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。 它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。 ![18](src/main/resources/static/readmeImg/18.png) > 线程池和连接池等就是享元模式的具体的实现。其侧重点在于通过列表来为维护所有的共享对象。 ### 15 command 命令模式 命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列种,且能实现可撤销操作。 ![19](src/main/resources/static/readmeImg/19.png) > 命令模式的侧重点在于将请求方法参数化、延迟请求的执行等,类似于消息队列的机制。 ### 16 builder 生成器(建造者)模式 建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。 它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。 ![21](src/main/resources/static/readmeImg/21.png) ![20](src/main/resources/static/readmeImg/20.png) > 建造者模式的侧重点在于对复杂对象的解构,分解成多个简单对象。由于集成@Builder注解,使用起来非常的简单方便,具体用法也符合函数式编程的风格。 ### 17 prototype 原型模式 原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。 在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。 ![22](src/main/resources/static/readmeImg/22.png) ![23](src/main/resources/static/readmeImg/23.png) > 原型模式的侧重点在于复杂对象自我复制,在对象内部有实现克隆方法。 > 原型模式和实现Cloneable或Object的clone()方法的操作结果是一样。区别在于原型模式是复杂对象的复制,且clone()方法是内部实现的。 ### 18 memento 备忘录模式 备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。 ![24](src/main/resources/static/readmeImg/24.png) ![25](src/main/resources/static/readmeImg/25.png) > 备忘录模式的侧重点在于维护一个历史对象数据栈,并提供操作方法。 ### 19 iterator 迭代器模式 迭代器模式是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。 ![26](src/main/resources/static/readmeImg/26.png) 其中,java list的迭代器即是实现了该模式。 ![27](src/main/resources/static/readmeImg/27.png) > 迭代器模式的侧重点在于对集合的遍历操作,该模式在java中应用的十分广泛,map、list、set的迭代器就是该模式的具体体现。 ### 20 composite 组合模式 组合模式是一种结构型设计模式,你可以使用它将对象组合成树状结构,并且能像使用独立对象一样使用它们。 ![28](src/main/resources/static/readmeImg/28.png) ![29](src/main/resources/static/readmeImg/29.png) > 组合模式用于对层级对象做操作。 ### 21 bridge 桥接模式 桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。 它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。 ![30](src/main/resources/static/readmeImg/30.png) ![31](src/main/resources/static/readmeImg/31.png) > 桥接模式的侧重点在于通过组合的方法来处理继承关系。 > 桥接模式和组合模式是比较相似的,它们的区别在于桥接模式处理的是类对象的父子关系,且没有中心对象。组合模式处理的则是类对象的兄弟关系,且有中心对象负责处理这个关系。 ### 22 mediator 中介者模式 中介者模式是一种行为设计模式,能让你减少对象之间的混乱无序的依赖关系。该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作。 ![32](src/main/resources/static/readmeImg/32.png) > 中介者模式侧重于通过中介对象来和其他对象做交互,类似于计算网络的星形结构。 ### 23 visitor 访问者模式 访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类, 使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。 它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。 ![33](src/main/resources/static/readmeImg/33.png) > 访问者模式的侧重点在于实例化对象对外提供修改自身数据和操作的方法,方便从外部修改数据和操作。 > 访问者模式、代理模式、装饰器模式、适配器模式四者比较相似,后面三者的区别见代理模式部分。访问者模式的侧重点在于提供外部修改自身数据和操作的方法。 Java设计模式通常遵循七大设计原则,这些原则有助于提高代码的可维护性、灵活性和可扩展性。 1.单一职责原则(SRP)、2.开放-封闭原则(OCP)、3.里氏替换原则(LSP)、4.接口隔离原则(ISP)、5.依赖倒置原则(DIP)6.合成/聚合复用原则(CARP)、7.迪米特法则(最少知识原则(Law of Demeter, LOD)) 以下是每个原则的简述和举例: 1. **单一职责原则(Single Responsibility Principle, SRP)** - 简述:一个类应该只有一个引起它变化的原因,即一个类只负责一项职责。 - 举例:一个处理用户登录的类,只应该关心登录逻辑,而不负责发送登录结果的邮件或短信通知。 2. **开闭原则(Open/Closed Principle, OCP)** - 简述:软件实体应当对扩展开放,对修改关闭。这意味着设计时应当使系统容易扩展,但不通过修改现有代码来增加新功能。 - 举例:使用接口和抽象类来允许新的子类来扩展功能,而不是修改现有的类。 3. **里氏替换原则(Liskov Substitution Principle, LSP)** - 简述:子类型必须能够替换掉它们的父类型,即基类可以被子类无缝替换,而不影响程序的行为。 - 举例:一个图形接口定义了一个绘制方法,圆形和正方形都实现了这个接口,可以互换使用而不影响调用者。 4. **接口隔离原则(Interface Segregation Principle, ISP)** - 简述:客户端不应该依赖于它不使用的接口。一个类不应该被强制实现它不需要的接口。 - 举例:定义多个专门的接口,而不是一个庞大的接口,让实现类根据自己的需要实现相应的接口。 5. **依赖倒置原则(Dependency Inversion Principle, DIP)** - 简述:高层模块不应依赖于低层模块,两者都应该依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象。 - 举例:一个高层的业务逻辑模块不应该直接依赖于低层的数据访问代码,而是通过接口或抽象类来解耦。 6. **合成复用原则(Composite Reuse Principle, CRP)** - 简述:尽量使用对象的组合/聚合来实现,而不是通过继承关系来复用代码。 - 举例:通过将对象包含在其他对象中来复用功能,而不是通过继承一个类。 7. **迪米特法则(最少知识原则(Law of Demeter, LOD))** - 简述:一个对象应该对其他对象有最少的了解,只与直接的朋友通信,不与“陌生人”说话。 - 举例:一个类的方法应该只调用自己内部的方法,或者调用其直接聚合的对象的方法,而不是调用聚合对象内部的方法。 这些原则相互关联,共同作用于设计模式的实现,帮助开发者创建出结构清晰、易于维护和扩展的系统。 ### 接口隔离原则 ![img_3.png](img_3.png) ![img_1.png](img_1.png) ![img_4.png](img_4.png) jdbc的实现机制,jdbc的驱动(接口的实现类)就是低层模块,而调用jdbc的类就是高层模块,两者依赖于jdbc的接口抽象定义 ###1.1 JDBC概念 JDBC 就是使用Java语言操作关系型数据库的一套API 全称:( Java DataBase Connectivity ) Java 数据库连接 我们开发的同一套Java代码是无法操作不同的关系型数据库,因为每一个关系型数据库的底层实现细节都不一样。如果这样,问题就很大了,在公司中可以在开发阶段使用的是MySQL数据库,而上线时公司最终选用oracle数据库,我们就需要对代码进行大批量修改,这显然并不是我们想看到的。 我们要做到的是同一套Java代码操作不同的关系型数据库,而此时sun公司就指定了一套标准接口(JDBC),JDBC中定义了所有操作关系型数据库的规则。众所周知接口是无法直接使用的,我们需要使用接口的实现类,而这套实现类(称之为:驱动)就由各自的数据库厂商给出。 ###1.2 JDBC本质 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口 各个数据库厂商去实现这套接口,提供数据库驱动jar包 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类 ###1.3 JDBC好处 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发 可随时替换底层数据库,访问数据库的Java代码基本不变 ###Java操作数据库的流程 第一步:编写Java代码 第二步:Java代码将SQL发送到MySQL服务端 第三步:MySQL服务端接收到SQL语句并执行该SQL语句 第四步:将SQL语句执行的结果返回给Java代码 ![img_5.png](img_5.png)