当前位置: 首页 > news >正文

java中常用的设计模式

目录

  • 分类
    • 创建型模式
    • 结构型模式
    • 行为型模式
  • 代码案例
    • 单例模式
      • 饿汉模式
        • 说明
        • 步骤
        • 代码
        • 运行结果
      • 懒汉模式
        • 说明
        • 步骤
        • 代码
        • 运行结果
    • 原型模式
      • 步骤
      • 代码
      • 运行结果

分类

总体来说设计模式分为三大类:

创建型模式

  • 工厂方法模式:定义一个接口用于创建对象,但让子类决定实例化哪个类。
  • 抽象工厂模式:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。
  • 单例模式:确保一个类只有一个实例,并提供全局访问点。
  • 建造者模式:使用多个简单的对象一步步构建成一个复杂的对象。
  • 原型模式:通过复制现有的实例来创建新的对象,而不是通过构造函数。

结构型模式

  • 适配器模式:将一个类的接口转换成客户端期望的另一个接口。
  • 装饰器模式:动态地给一个对象添加一些额外的职责,而不会影响到其他对象。
  • 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
  • 外观模式:为一组接口提供一个统一的高层接口,使子系统更易使用。
  • 桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  • 组合模式:将对象组合成树形结构以表示“部分-整体”层次结构。
  • 享元模式:使用共享对象来高效地支持大量细粒度的对象。

行为型模式

  • 策略模式:定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换。
  • 模板方法模式:定义一个操作中的算法的骨架,将一些步骤延迟到子类中。
  • 观察者模式:定义一种依赖关系,让多个观察者对象同时监听某一个主题对象。
  • 迭代子模式:提供一种方法顺序访问一个集合对象中的各个元素,而无需暴露该对象的内部表示。
  • 责任链模式:通过将请求传递给链中的多个处理者,直到有一个处理者处理这个请求。
  • 命令模式:将请求封装成一个对象,以便使用不同的请求、队列或日志请求,并支持可撤销操作。
  • 备忘录模式:在不暴露对象内部状态的情况下,保存和恢复对象的状态。
  • 状态模式:允许一个对象在其内部状态改变时改变它的行为。
  • 访问者模式:表示一个作用于某对象结构中的各个元素的操作,它使你可以在不改变这些元素的类的前提下定义作用于这些元素的新操作。
  • 中介者模式:定义一个对象,用来封装一系列对象之间的交互,使得这些对象不需要直接交互。
  • 解释器模式:给定一个语言,定义它的文法,并解释句子。

代码案例

单例模式

确保一个类只有一个实例,并提供全局访问点

饿汉模式

说明

在类创建的时候就开始实例化对象;不管用没用到,一开始就创建。

步骤
  1. 创建静态对象,对象直接实例化
  2. 私有化构造方法
  3. 提供获取实例的方法,返回实例
代码
public class Eager {// 类创建时候立即创建实例 ,且实例不可修改private static final Eager eager = new Eager();// 私有化构造器private Eager() {}// 对外暴露获取实例的方法public static Eager getInstance() {return eager; // 永远返回的都是同一个对象,此对象在类加载的时候就创建了。}public static void main(String[] args) {// 创建实例Eager eager1 = Eager.getInstance(); // 通过getInstance()方法获取实例Eager eager2 = new Eager(); // 创建新实例Eager eager3 = Eager.getInstance(); // 通过getInstance()方法获取实例System.out.println("eager1 等于 eager2 : "+(eager1 == eager2));// 判断eager1 和 eager2 是否相等。结果:falseSystem.out.println("eager1 等于 eager3 : "+(eager1 == eager3));// 判断eager1 和 eager3 是否相等。结果:true 。 说明通过getInstance()获取到的对象是同一个System.out.println("eager2 等于 eager3 : "+(eager2 == eager3));// 判断eager2 和 eager3 是否相等。结果:falseSystem.out.println();// 打印对象的内存地址System.out.println("eager1内存地址: "+eager1.hashCode());System.out.println("eager2内存地址: "+eager2.hashCode());System.out.println("eager3内存地址: "+eager3.hashCode());}
}
运行结果
eager1 等于 eager2 : false
eager1 等于 eager3 : true
eager2 等于 eager3 : falseeager1内存地址: 125130493
eager2内存地址: 914504136
eager3内存地址: 125130493

懒汉模式

说明

类加载时不实例化,调用时才实例化。

步骤
  1. 创建静态对象,对象直接实例化
  2. 私有化构造方法
  3. 提供获取实例的方法,判断对象是否为空,为空则实例化。实例化之前加锁,保证线程安全。返回实例。
代码
public class Lazy {// 初始化不实例化private volatile static Lazy lazy;// 私有化构造方法private Lazy() {}// 对外开放获取实例的方法public static Lazy getInstance() {if (lazy == null){// 防止并发时创建多个实例。在创建时加锁。只有一个线程能获取到锁,其他线程会等待。只要其中一个线程把对象实例化后,之后其他线程就能直接获取到对象实例,不会再实例化新对象。synchronized (Lazy.class){lazy = new Lazy();}}return lazy;}public static void main(String[] args) {// 创建实例Lazy lazy1 = Lazy.getInstance(); // 通过getInstance()方法获取实例Lazy lazy2 = new Lazy(); // 创建新实例Lazy lazy3 = Lazy.getInstance(); // 通过getInstance()方法获取实例System.out.println("lazy1 等于 lazy2 : "+(lazy1 == lazy2));// 判断lazy1 和 lazy2 是否相等。结果:falseSystem.out.println("lazy1 等于 lazy3 : "+(lazy1 == lazy3));// 判断lazy1 和 lazy3 是否相等。结果:true 。 说明通过getInstance()获取到的对象是同一个System.out.println("lazy2 等于 lazy3 : "+(lazy2 == lazy3));// 判断lazy2 和 lazy3 是否相等。结果:falseSystem.out.println();// 打印对象的内存地址System.out.println("lazy1内存地址: "+lazy1.hashCode());System.out.println("lazy2内存地址: "+lazy2.hashCode());System.out.println("lazy3内存地址: "+lazy3.hashCode());}
}
运行结果
lazy1 等于 lazy2 : false
lazy1 等于 lazy3 : true
lazy2 等于 lazy3 : falselazy1内存地址: 125130493
lazy2内存地址: 914504136
lazy3内存地址: 125130493

原型模式

通过复制现有的实例来创建新的对象,而不是通过构造函数。

步骤

  1. 创建一个实体类,实现Cloneable接口
  2. 重写clone方法

代码

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Prototype implements Cloneable {private String name; // 实体属性private int age; // 实体属性// 如果属性为对象,则对象也需要实现Cloneable接口private Student student; // 实体属性-对象// 重写clone方法,返回克隆的新对象,新对象类型强制转换成Prototype@Overrideprotected Prototype clone(){Prototype clone = null;try {clone = (Prototype) super.clone();clone.setStudent(this.student.clone()); // 对实体属性进行深度克隆} catch (CloneNotSupportedException e) {System.out.println("Prototype 对象克隆失败");throw new RuntimeException(e);}return clone;}
}// 主要用于给Prototype做对象属性
@Data
@AllArgsConstructor
@NoArgsConstructor
class Student implements Cloneable {private String studentNumber;@Overrideprotected Student clone() {try {return (Student) super.clone();} catch (CloneNotSupportedException e) {System.out.println("Student 对象克隆失败");throw new RuntimeException(e);}}
}// 测试方法
class Test {public static void main(String[] args) {// 创建一个原始对象Prototype prototype = new Prototype("张三", 18, new Student("0000"));System.out.println("原始对象: \n\t " + prototype + " \n\t 原始对象的地址:"+ prototype.hashCode());System.out.println();// 克隆原始对象Prototype clone = prototype.clone();System.out.println("克隆对象: \n\t " + clone + " \n\t 克隆对象的地址:"+ clone.hashCode());System.out.println();System.out.println("经过克隆后原始对象和克隆对象数据:\n\t原始对象:"+ prototype + "\n\t克隆对象:" + clone);System.out.println("\n\t原始对象内存地址:"+ prototype.hashCode() + "\n\t克隆对象内存地址:" + clone.hashCode());System.out.println();System.out.println("原始对象实体Student属性的内存地址:"+prototype.getStudent().hashCode());System.out.println("克隆对象未覆盖原始实体Student属性时,实体属性的内存地址:"+clone.getStudent().hashCode());System.out.println();clone.setName("李四");clone.setAge(20);clone.getStudent().setStudentNumber("33333");System.out.println("克隆对象覆盖原始实体属性后:\n\t原始对象:"+ prototype + "\n\t克隆对象:" + clone);System.out.println("\n\t原始对象内存地址:"+ prototype.hashCode() + "\n\t克隆对象内存地址:" + clone.hashCode());System.out.println();System.out.println("原始对象实体Student属性的内存地址:"+prototype.getStudent().hashCode());System.out.println("克隆对象覆盖原始实体Student属性后,实体属性的内存地址:"+clone.getStudent().hashCode());System.out.println();}
}

运行结果

原始对象: Prototype(name=张三, age=18, student=Student(studentNumber=0000)) 原始对象的地址:47464179克隆对象: Prototype(name=张三, age=18, student=Student(studentNumber=0000)) 克隆对象的地址:47464179经过克隆后原始对象和克隆对象数据:原始对象:Prototype(name=张三, age=18, student=Student(studentNumber=0000))克隆对象:Prototype(name=张三, age=18, student=Student(studentNumber=0000))原始对象内存地址:47464179克隆对象内存地址:47464179原始对象实体Student属性的内存地址:1477691
克隆对象未覆盖原始实体Student属性时,实体属性的内存地址:1477691克隆对象覆盖原始实体属性后:原始对象:Prototype(name=张三, age=18, student=Student(studentNumber=0000))克隆对象:Prototype(name=李四, age=20, student=Student(studentNumber=33333))原始对象内存地址:47464179克隆对象内存地址:98626212原始对象实体Student属性的内存地址:1477691
克隆对象覆盖原始实体Student属性后,实体属性的内存地址:48669614

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 苍穹外卖day10
  • uniapp快速回顾,新学websocket连接和BLE连接
  • TinyEngine是什么?
  • 大疆秋招笔试
  • 【数学建模】MATLAB快速入门
  • 深度学习的数学之魂:传统机器学习的超越者
  • 深度学习基础—学习率衰减与局部最优问题
  • Java-Web面试题汇总
  • XML Schema 复合元素 - 仅含文本
  • Python实现水果忍者(开源)
  • Openstack 所需要的共享服务组件及核心组件
  • 代码随想录:动态规划6-10
  • TCP/IP 协议及其协议号
  • Webrtc之SDP协议
  • 20221元组
  • [笔记] php常见简单功能及函数
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • 2017前端实习生面试总结
  • bootstrap创建登录注册页面
  • CentOS6 编译安装 redis-3.2.3
  • Git 使用集
  • JavaScript 基本功--面试宝典
  • Js基础——数据类型之Null和Undefined
  • KMP算法及优化
  • MySQL的数据类型
  • quasar-framework cnodejs社区
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 服务器之间,相同帐号,实现免密钥登录
  • 事件委托的小应用
  • 一个JAVA程序员成长之路分享
  • 一天一个设计模式之JS实现——适配器模式
  • 用element的upload组件实现多图片上传和压缩
  • 中文输入法与React文本输入框的问题与解决方案
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • #13 yum、编译安装与sed命令的使用
  • #includecmath
  • (3)选择元素——(17)练习(Exercises)
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (Java入门)学生管理系统
  • (LeetCode 49)Anagrams
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (力扣)循环队列的实现与详解(C语言)
  • (一一四)第九章编程练习
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转载)(官方)UE4--图像编程----着色器开发
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET CF命令行调试器MDbg入门(一)
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET/C# 项目如何优雅地设置条件编译符号?