爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      GoF23种(部分)软件设计模式【核心理解】

      首页 知识中心 软件开发 文章详情页

      GoF23种(部分)软件设计模式【核心理解】

      2024-04-23 09:44:00 阅读次数:50

      Java,软件设计模式

      设计模式复习

      1. 面向对象设计原则

      1.1 可维护性较低的软件设计

      • 过于僵硬
      • 过于脆弱
      • 复用率低
      • 黏度过高

      1.2 一个好的系统设计

      • 可扩展性
      • 灵活性
      • 可插入性

      复用:一个软件的组成部分可以在同一个项目的不同地方甚至在不同的项目重复使用。

      面向对象设计复用的目标:实现支持可维护性的复用。(抽象、继承、封装、多态)

      重构:在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能、使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。


      1.3 七大设计原则

      • 单一职责原则(Single Responsibility Principle , SRP):一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。
      • 单一职责用于控制类的粒度大小。
      • 是实现高内聚低耦合的指导方针
      • 开闭原则(Open-Closed Principle , OCP):一个软件实体应当对扩展开放,对修改关闭。
      • 抽象化是开闭原则的关键
      • 里氏代换原则(Liskov Substitution Principle , LSP ):所有引用基类(父类)的地方必须能透明地使用其子类的对象。
      • 里氏代换原则是实现开闭原则的重要方式之一
      • 子类必须实现父类的所有方法
      • 尽量把父类设计为抽象类或者接口
      • 依赖倒转原则(Dependence Inversion Principle . DIP ):高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不依赖于细节,细节应该依赖于抽象。
      • 要针对接口编程,不要针对实现编程。
      • 开闭原则是面向对象设计的目标,依赖倒转原则就是面向对象设计的主要手段。
      • 类之间的耦合
      • 依赖注入:将一个类的对象传入另一个类,注入时尽量注入父类对象,程序运行时通过子类对象覆盖父类对象。
      • 构造注入、Setter注入、接口注入
      • 接口隔离原则(Interface Segregation Principle , ISP):客户端不应该依赖那些它不需要的接口(方法)。
      • 大接口要分割成一些更细小的接口。
      • 使用多个专门的接口,而不使用单一的总接口。
      • 接口仅仅提供客户端需要的方法。
      • 合成复用原则(Composite Reuse Principle , CRP ):又称为组合/聚合复用原则,尽量使用对象组合,而不是继承来达到复用的目的。
      • 在一个新的对象里通过关联关系来使用一些已知对象,使之成为新对象的一部分。
      • 迪米特法则(Law of Demeter , LoD ):又称为最少知识原则,不要和“陌生人”说话只与你的直接朋友通信。

      2. 初识设计模式

      2.1 设计模式定义

      设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码,让代码更容易被他人理解、保证代码的可靠性。

      2.2 设计模式基本要素

      • 模式名称、问题、目的、解决方案、效果、实例代码和相关设计模式
      • 关键元素包括以下四个方面
      • 模式名称:通过一两个词来描述模式的问题、解决方案和效果,多数模式是根据其功能或者模式结构来命名的。
      • 问题:描述了应该在何时使用模式,包含了设计中存在的问题以及问题存在的原因。
      • 解决方案:描述了设计模式的组成成分,以及这些组成成分之间的相互关系,各自的职责和协作方式。解决方案通过类图和核心代码来进行说明。
      • 效果:描述了模式应用的效果以及在使用模式时应该权衡的问题。包含了模式的优缺点分析

      2.3 设计模式的分类

      • 根据目的(模式是用来做什么的)可以分为创建型(Creational)、结构型(Structural)和行为型(Behavioral)三种
      • 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。
      • 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。
      • 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。
      • 根据范围(模式主要是用于类之间的关系还是处理对象之间的关系)可以分为类模式和对象模式两种
      • 类模式处理类和子类关系,这些关系通过继承确立,在编译的时候就被确定了,是静态的。
      • 对象模式处理对象的关系,时刻变化,有动态性。

      3.深入理解设计模式

      3.1 建造者模式(Builder)

      例子:根据计算机组件组装不同的计算机。

      用这个例子来理解一下创建者模式:首先这个模式做的事情是这样的,现在有一堆计算机零件,比如说一块硬盘它可以放在笔记本电脑上也可以放在台式机上,那么建造者模式就是把不同电脑的构建和表示分离,提供一个计算机产品类,里面包含了计算机的零件,之后提供一张“图纸”这张图纸就是一个抽象建造者接口,这个接口提供了创建的方法以及返回复杂对象的方法,具体的建造者会实现这个接口,用这张“图纸”来创造不同类型的计算机。

      具体角色:

      • 具体产品角色:Computer
      • 抽象建造者:ComputerBuilder
      • 具体建造者:DeskTopComputer、LapTopComputer
      • 指挥者:ComputerWaiter

      注意点:

      抽象建造者里要去new一个具体产品。
      protected Computer computer = new Computer();
      抽象建造者里需要定义一个返回复杂产品的方法
      public Computer getComputer(){
      return computer;
      }

      具体建造者继承自抽象建造者,实现里面的所有建造方法!
      public class DeskTopBuilder extends ComputerBuilder

      指挥者类是真正干活的类
      public class ComputerWaiter {
      private ComputerBuilder cb;
      public void setCb(ComputerBuilder cb){
      this.cb=cb;
      }
      public Computer construct(){
      cb.buildCPU();
      cb.buildHardDisk();
      cb.buildMainFrame();
      cb.buildMemory();
      return cb.getComputer();
      }
      }
      这个类需要拥有一个抽象建造者的对象,利用这个对象调用其建造的方法来完整一个具体的产品并调用其方法把这个产品返回!

      总结:

      • 具体产品类提供了一个产品需要的零件。
      • 抽象建造类相当于是总工程师画的一张图纸,这张图纸总体上实现了这个产品的建造,里面需要一个创建(new)一个具体产品的成员对象,并提供返回这个对象的方法。
      • 具体建造类相当于是拿着总工程师的图纸根据实际的需要进行了二次加工,这个类继承自抽象建造类,需要实现总图纸的所有方法,不过具体的建造细节可以自己决定。
      • 指挥者类是真正干活的工人,这个类拿着实际的图纸来完成工作做出具体的产品,这个类需要聚合抽象建造类,并提供setter接口方法,让外界传入具体的“图纸”参数,然后进行建造。

      核心理解

      建造者模式的核心在于抽象建造者类,这个类要做的事情是定义方法:首先这个类是用来建造一个实例对象的,所以一定要new一个新的产品对象作为其属性成员,然后定义建造的接口方法,根据具体需要被建造的实例的setter方法提供不同的多个建造方法接口,最后需要一个方法返回最终建造完成的对象。

      这个抽象建造方法就是一张建造的图纸,后面实现这个接口的类是具体的建造图纸,把具体的建造图纸用set注入的方式给指挥者类(相当于工人)让指挥者类干活,最后根据具体图纸完成一个实例产品!


      3.2 原型模式(ProtoType)

      具体角色:

      • ProtoType抽象原型类
      • ConcreteProtoType具体原型类

      步骤:

      1. 实现一个接口:Cloneable
      2. 重写一个方法:clone
      pubilc Object clone()

      object = super.clone() ;

      return object;
      • 浅克隆:复制对象的引用,对象的属性仍然指向同一处。
      • 深克隆:不止复制对象的引用,而且要把对象的所有属性全部克隆一次,两个对象的属性将不会指向同一块区域,从而实现两个对象彻底分离。

      核心理解

      原型模式只做了一件事情,就是克隆一份一模一样的自己并返回。

      1. 实现一个接口Cloneable
      2. 调用一个方法:object = super.clone() ;
      3. 返回这个object

      3.3 单例模式(Singleton)

      注意点:

      • 静态私有成员变量。
      • 私有构造函数。
      • 静态公有工厂方法,返回唯一对象实例,方法中判断对象是否为空,如果为空则new一个新对象返回,俄国不为空,则直接将私有成员变量对象返回。
      package com.a007;

      public class StuNo
      {
      //静态私有成员变量
      private static StuNo instance=null;
      private String no;
      //私有构造方法
      private StuNo()
      {
      }
      //静态公有工厂方法,返回唯一实例
      public static StuNo getInstance()
      {
      if(instance==null)
      {
      System.out.println("新学号");
      instance=new StuNo();
      instance.setStuNo("20194074");
      }
      else
      {
      System.out.println("学号重复,获得旧学号");
      }
      return instance;
      }

      private void setStuNo(String no)
      {
      this.no=no;
      }

      public String getStuNo()
      {
      return this.no;
      }

      }

      核心理解

      单例模式做的事情是保证一个类有且只有一个实例对象!

      1. 首先要保证这个类的构造方法是私有的
      2. 其次要保证这个对象作为成员属性是静态私有的
      3. 最后提供一个公有的对外接口返回这个实例化的对象

      3.4 适配器模式(Adapter)

      用途:将一个类的接口转换成客户希望的另一个类的接口。

      例子:电脑网线USB转接器

      角色:

      电脑(客户端)、网线、转接器、目标接口NetToUsb

      • 目标接口或抽象类(目标抽象类或目标抽象接口):这里例子中就是目标接口USB。
      • 适配者类(需要适配的类 Adaptee):它定义了一个已经存在的接口,这个接口需要被适配。在这个例子中网线类就是那个已经存在的接口,但是网线不可以直接插到电脑的USB上。
      • 适配器类(Adapter):包装网线,让网线支持USB接口,把网线插到USB上并处理请求。
      • 适配器类需要同时和两个类打交道,它要把网线和电脑的USB接口连接在一起。有两种方式,
      • 一种是继承要被适配的类(网线类)同时实现目标接口。
      • 另一种是使用组合模式,不去继承适配者类,而是使用聚合的方式,让网线类作为适配器类的一个成员变量,然后再去实现目标抽象接口。

      分类:

      • 类适配器:继承模式,继承需要被适配的类,实现目标抽象接口。
      • 对象适配器:组合模式,把需要适配的类作为成员属性变量,同时实现目标抽象接口。

      类图:(双向适配)

      GoF23种(部分)软件设计模式【核心理解】


      核心理解

      适配器模式做的事情是这样的:

      有两个不相干的类,但是它们想组合到一起使用,那么就通过一个适配器把二者适配在一起使用。

      比如说:电脑有一个USB接口,而网线的接头不是USB的,可是电脑想上网,那么就需要一个接口转接的适配器来完成这个工作,这时候会出现三个类。

      1. 网线类:这个类提供了具体要实现的业务方法,也就是它可以完成上网这件事,比如说有一个方法是net()
      2. USB接口类:这个接口是用户想要的接口,用户希望通过USB接口完成上网这件事,比如说有一个方法是execute()
      3. 转接器类:这个类来完成二者的适配:首先实现USB接口,然后或者通过继承网线类或者通过组合网线类,选择二者的任意一个方式,重写USB接口里的方法execute(),在这个方法里去调用网线类的真实业务方法net()来完成上网这件事
      4. 客户端在调用时,只需要把实例化的网线类通过set注入交给适配器,然后通过调用适配器类的execute()方法就可以完成上网这件事情!

      3.5 桥接模式(Bridge)

      GoF23种(部分)软件设计模式【核心理解】

      GoF23种(部分)软件设计模式【核心理解】

      GoF23种(部分)软件设计模式【核心理解】

      图片来自bilibili遇见狂神说


      核心理解

      桥接模式做了这样一件事情:

      就像图中所示:如果想要一个联想的台式电脑,那么就需要两层继承来拿到这个对象(类),第一这是低效率的,第二这是一种静态的定死的方式,扩展性很差。桥接模式的思想是把抽象化和实现化进行解耦分离,比如说无论有多少个品牌,抽象来看它们都只是品牌,无论有多少种电脑,它们都只是电脑。这样的话可以抽象出两个维度,一个是类型、另一个是品牌。具体的实现就是自由组合:XX品牌的XX种类电脑。

      优化:本来如果要这九种电脑需要3*3=9个类,现在需要这些电脑只需要3+3=6个类,如果数量级更大,桥接模式的好处可想而知,可以大大减少子类的个数!

      根据依赖倒转原则,实现要依赖抽象,所以首先会有一个抽象的电脑类,这个抽象类的子类是各种类型的电脑,其次需要一个电脑的品牌接口,实现这个接口的类是各种品牌!

      这个抽象电脑类和品牌接口类是组合的关系,抽象电脑类通过Setter方法注入一个具体的电脑品牌对象,然后用其方法结合自身的电脑种类获得这个品牌的各种类型的电脑!


      补充:【抽象类和接口的区别】

      含有abstract修饰符的class即为抽象类,abstract 类不能创建实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

      接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

      下面比较一下两者的语法区别:

      1. 抽象类可以有构造方法,接口中不能有构造方法。
      2. 抽象类中可以有普通成员变量,接口中没有普通成员变量
      3. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
      4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然

      eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

      1. 抽象类中可以包含静态方法,接口中不能包含静态方法
      2. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
      3. 一个类可以实现多个接口,但只能继承一个抽象类。

      3.6 装饰模式(Decorator)

      定义:动态地给一个对象增加一些额外的职责。

      角色:

      • 抽象构件:Component
      • 具体构件:ConcreteComponent
      • 抽象装饰类:Decorator
      • 具体装饰类:ConcreteDecorator

      模式分析:

      具体构件类和抽象构件类都实现了抽象构件接口,模式的关键在于抽象装饰类,这个类实现了抽象构件接口并且组合了抽象构件,在其构造函数中设置参数注入具体构件对象,在其装饰方法中调用这个注入的构件类已有的方法,再通过具体装饰类的继承,添加其他方法和功能。

      GoF23种(部分)软件设计模式【核心理解】


      核心理解

      装饰模式做的事情是动态修改被装饰者的一些属性方法等等。

      根据依赖倒转原则,待装饰的类和装饰者类都要实现自同一个抽象构件接口,在装饰者类的构造方法里要注入一个待装饰者对象,装饰者类和抽象构件接口是组合关系和接口实现关系,在装饰者类中提供一个可扩展的方法供子类重写。

      具体的装饰者类继承抽象装饰者类,重写其扩展方法完成对待装饰对象的装饰!


      3.7 外观模式(Facade)

      定义:外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统的一组接口提供 了一个一致的界面。

      实例:一个电源总开关可以控制四盏灯、一个风扇、一台空调和一个电视机的启动和关闭。

      类图:

      GoF23种(部分)软件设计模式【核心理解】


      核心理解

      外观模式做的事情是这样的:

      比如说你现在想把家里的灯关了、把空调关了、把电视机也关了。正常的过程是你要一个个去把它们关闭,但是如果给你一个统一的关闭按钮,只要你按这一个按钮,这三种电器就会同时关闭,这样的一个按钮的实现,就是外观模式的核心!

      使用简单的关联关系,实现对多个对象的方法的同时调用,统一分配!


      3.8 代理模式(Proxy)

      定义:

      给某个对象提供一个代理,并由代理对象控制对原对象的引用。

      角色:

      • 抽象主题角色:里面包含了抽象的业务操作。
      • 代理主题角色:实现抽象主题接口,关联真实主题角色,对真实主题角色的一些业务进行一些预先处理和延后处理。
      • 真实主题角色:里面包含的真实的业务需求,客户端调用的时只需要面向代理角色,根据不同的客户,代理角色将给出不同的业务实现,代替真实主题角色进行业务的安排。

      GoF23种(部分)软件设计模式【核心理解】


      核心理解

      代理模式的关键在于:

      首先根据依赖倒转原则:具体主题类和代理主题类都要实现自同一个抽象主题角色。

      代理主题类关联真实主题类,代替真实主题针对不同的客户做出不同的处理!


      3.9 职责链模式(Chain of Responsibility)

      定义:避免请求的发送者和接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,沿着这条链传递请求,直到有对象处理它为止。

      角色:

      • 抽象处理者:Handler
      • 具体处理者:ConcreteHandler
      • 客户类:Client

      模式分析:

      关键在于抽象处理者类的设计:很多对象由每一个对象对其下家的引用而连接在一起。

      抽象处理者典型代码:

      //审批者类:抽象处理者
      abstract class Approver {
      protected Approver successor; //定义后继对象
      protected String name; //审批者姓名

      public Approver(String name) {
      this.name = name;
      }

      //设置后继者
      public void setSuccessor(Approver successor) {
      this.successor = successor;
      }

      //抽象请求处理方法
      public abstract void processRequest(PurchaseRequest request);
      }

      具体处理者典型代码:

      //董事长类:具体处理者
      class ViceManager extends Approver {
      public ViceManager(String name) {
      super(name);
      }
      //具体请求处理方法
      public void processRequest(PurchaseRequest request) {
      if (request.getAmount() < 100000) {
      System.out.println("副总经理" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount() + "元,采购目的:" + request.getPurpose() + "。"); //处理请求
      }
      else {
      this.successor.processRequest(request); //转发请求
      }
      }
      }

      客户端调用典型代码:轮流设置下家

      position1.setSuccessor(position2);
      position2.setSuccessor(position3);
      position3.setSuccessor(position4);
      position4.setSuccessor(meeting);
      package com.c015;

      public class Client {
      public static void main(String[] args) {
      Approver position1,position2,position3,position4,meeting; // 多个处理者
      position1 = new Director("甲");
      position2 = new PartManager("乙");
      position3 = new ViceManager("丙");
      position4 = new Manager("丁");
      meeting = new Congress("职工大会");
      //创建职责链
      position1.setSuccessor(position2);
      position2.setSuccessor(position3);
      position3.setSuccessor(position4);
      position4.setSuccessor(meeting);
      //创建采购单
      PurchaseRequest pr1 = new PurchaseRequest(5000,10001,"XXX");
      position1.processRequest(pr1);

      PurchaseRequest pr2 = new PurchaseRequest(45000,10002,"XXX");
      position1.processRequest(pr2);

      PurchaseRequest pr3 = new PurchaseRequest(77000,10003,"XXX");
      position1.processRequest(pr3);

      PurchaseRequest pr4 = new PurchaseRequest(150000,10004,"XXX");
      position1.processRequest(pr4);

      PurchaseRequest pr5 = new PurchaseRequest(800000,10005,"XXX");
      position1.processRequest(pr5);
      }
      }

      核心理解

      职责链模式关键在于设置职责的下家!

      抽象处理者类要有一个自身的对象作为成员属性变量,并通过一个set方法完成赋值,之后要提供一个具体处理的方法接口供子类重写!

      后续的子类重写具体的处理办法,如果处理不了,再次调用父类的处理方法直接把请求交给下家来完成!


      3.10 命令模式(Command)

      定义:

      将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化。

      本质上是对命令进行封装,将发出命令的责任和执行命令的责任分隔开。

      角色:

      • 接收者类:实现了具体的业务操作,拿电视机来说,这个类实现了电视机的开启和关闭的真实操作方法。
      • 抽象命令类:定义了一个执行命令的方法接口,由其子类实现。
      • 具体命令类(一个命令一个类):实现抽象命令接口,关联接收者类,调用接受者类中具体的一个命令,比如这个具体命令类是要开启电视机,那么执行命令的方法就调用接受者对象中的开启命令。
      • 调用者类:相当于遥控器,把所有可能的操作集合在一起,客户端只需要使用遥控器就可以完成所有命令的发起,构造方法(形参是是抽象命令队对象,实参是具体命令对象)完成所有具体命令对象的注入,提供执行命令的方法,用具体命令对象调用具体命令的执行方法。

      关键代码:

      //接收者:真正执行命令的对象
      public class Light {
      public void open(){
      System.out.println("打开电灯!");
      }
      }
      public interface Command {
      public void execute();
      }
      // 这是一个命令,所以需要实现Command接口
      public class LightOnCommand implements Command {
      Light light;

      // 构造器传入某个电灯,以便让这个命令控制,然后记录在实例变量中
      public LightOnCommand(Light light) {
      this.light = light;
      }

      // 这个execute方法调用接收对象的on方法
      public void execute() {
      light.on();
      }

      }
      public class SimpleRemoteControl {
      // 有一个插槽持有命令,而这个命令控制着一个装置
      Command slot;

      public SimpleRemoteControl() {}

      // 这个方法用来设置插槽控制的命令
      public void setCommand(Command command) {
      slot = command;
      }

      // 当按下按钮时,这个方法就会被调用,使得当前命令衔接插槽,并调用它的execute方法
      public void buttonWasPressed() {
      slot.execute();
      }
      }

      客户端使用

      public class RemoteControlTest {
      public static void main(String[] args) {
      // 遥控器就是调用者,会传入一个命令对象,可以用来发出请求
      SimpleRemoteControl remote = new SimpleRemoteControl();
      // 现在创建一个电灯对象,此对象也就是请求的接收者
      Light light = new Light();
      // 这里创建一个命令,然后将接收者传给它
      LightOnCommand lightOn = new LightOnCommand(light);

      // 把命令传给调用者
      remote.setCommand(lightOn);
      // 模拟按下按钮
      remote.buttonWasPressed();
      }
      }

      核心理解

      命令模式主要完成的事情是把命令的具体实施和命令的发出解耦。

      有一个具体干活的类(命令接收者类),这个类里有所有执行具体命令的方法。

      有一个抽象的命令类,这个类定义了一个执行的方法接口,然后它的子类(这些子类的个数和具体命令的个数是一致的,比如说那个具体干活的类需要做两件事,一个是打开电脑,一个是关闭电脑,那么就会有两个不同的子类来继承这个抽象的命令类!)继承这个类并重写它的执行命令的方法,这里有个点需要注意:这些子类需要关联那个命令接收者类,用那个类的方法来重写执行方法!


      3.11 迭代器模式(Iterator)

      定义:

      定义了遍历和访问元素的接口,一般声明如下方法:用于获取第一个元素的first(),用于访问下一个元素的next(),用于判断是否还有下一个元素的hasNext(),用于获取当前元素的currentItem()。

      3.12 观察者模式(Observer)

      定义:

      定义对象之间的一种一对多的依赖关系,使得每当一个对象的状态发生变化时,其相关的依赖对象都可以得到通知并被自动更新。

      模式主要用于多个不同的对象对一个对象的某个方法会做出不同的反应!

      比如猫叫之后狗会叫老鼠会逃跑,这时候猫就是被观察者,老鼠和狗都是观察者。

      角色:

      • 抽象目标:这是被观察的对象(抽象)
      • 这是核心,里面需要一个成员属性变量存储所有的观察者,需要定义add和remove观察者的方法,需要给出notify方法通知所有的观察者对象。
      • 具体目标(具体的被观察者):猫继承抽象目标类,实现里面的方法,写出猫的反应,并且循环输出所有观察者的反应。
      • 抽象观察者:接口,定义响应方法。
      • 具体观察者:实现抽象观察者方法,重写响应方法。
      • 客户端调用:先使用具体目标对象的add方法添加具体观察者对象,然后调用其notify方法通知观察者。

      核心理解

      观察者模式做的事情是这样的:

      有这么一个场景,比如说一个对象的某个变化会造成其他类的不同的反应,比如说股票的涨跌和股民的状态就是一种动态的关联变化,观察者模式就是来描述这样的一个场景的!

      具体是这样完成的:

      根据依赖倒转原则,首先需要一个抽象的被观察的类,这个类拥有的成员属性变量是和它有关系的那些观察者对象,一般是有多个对象,如果这个属性是一个集合,那么需要定义两个接口方法,一个增加一个删除,最后还需要一个描述自身状态的方法。

      具体的被观察者继承自抽象的被观察类, 这个类重写它的状态变化方法!注意这个方法需要遍历所有观察者对象的response方法

      观察者同样也需要进行抽象,需要一个观察者接口类,这个类只有一个方法就是response()

      具体的观察者实现这个接口,重写response方法!

      客户端在调用时,需要把观察者添加到被观察者里,然后调用被观察者的状态变化方法,就会看到它所有的观察者对这个状态做出的不同的反应!

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/reliableyang/5651656,作者:靠谱杨的挨踢IT生活,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:剑指Offer(20)--包含min函数的栈

      下一篇:单元测试

      相关文章

      2025-05-14 10:03:13

      arm架构下JAVA开发

      ARM(Advanced RISC Machine)是一种基于精简指令集计算(RISC)设计的处理器架构。它以高效、节能著称,因此广泛应用 于从智能手机到物联网设备的各个领域。

      2025-05-14 10:03:13
      Java , JVM , 嵌入式 , 架构 , 设备
      2025-05-14 10:02:58

      Java实现根据概率中奖率怎么算

      要实现根据概率计算中奖率的功能,可以使用 Java 编程语言编写一个简单的程序。

      2025-05-14 10:02:58
      Java , 概率 , 模拟 , 程序
      2025-05-14 09:51:21

      Java 代码本地设置Hadoop用户名密码

      在Hadoop环境中,通常使用Kerberos进行身份验证。但在一些开发或测试环境中,我们可能需要在本地代码中设置用户名和密码来模拟或进行简单的测试。

      2025-05-14 09:51:21
      Hadoop , Java , 代码 , 使用 , 用户名 , 认证
      2025-05-14 09:51:21

      java 判断map为null或者空

      java 判断map为null或者空

      2025-05-14 09:51:21
      Java , Map , null , 方法 , 是否 , 检查 , 示例
      2025-05-14 09:51:15

      java怎么对线程池做监控

      对Java线程池进行监控是确保系统性能和稳定性的重要部分。监控线程池可以帮助我们了解线程池的状态,如当前活跃线程数、任务队列长度、已完成任务数等。

      2025-05-14 09:51:15
      Java , 方法 , 监控 , 示例 , 线程 , 队列
      2025-05-13 09:53:23

      java动态获取实体类的字段

      在Java中,我们可以使用反射(Reflection)API来动态地获取实体类的字段。

      2025-05-13 09:53:23
      API , Java , 使用 , 字段 , 实体类 , 方法 , 获取
      2025-05-13 09:53:23

      Java静态变量在静态方法内部无法改变值

      在Java中,静态变量(也称为类变量)属于类本身,而不是类的任何特定实例。它们可以在没有创建类的实例的情况下访问和修改。如果我们发现在静态方法内部无法改变静态变量的值,这通常是因为我们的代码中有一些逻辑错误或误解。

      2025-05-13 09:53:23
      Java , 变量 , 实例 , 类名 , 访问 , 静态 , 静态方法
      2025-05-12 10:19:12

      springboot学习(2)

      springboot学习(2)

      2025-05-12 10:19:12
      Java , main , springboot , web , 启动 , 方法 , 浏览器
      2025-05-08 09:03:21

      基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】

      本项目是一套基于spring+jsp+mysql实现的Java web论坛系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

      2025-05-08 09:03:21
      Java , jsp , spring , 功能 , 源码
      2025-05-07 09:08:42

      Java中的异常体系

      Java中的异常体系

      2025-05-07 09:08:42
      Exception , Java , 异常 , 程序
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5226912

      查看更多

      最新文章

      arm架构下JAVA开发

      2025-05-14 10:03:13

      Java实现根据概率中奖率怎么算

      2025-05-14 10:02:58

      Java 代码本地设置Hadoop用户名密码

      2025-05-14 09:51:21

      java 判断map为null或者空

      2025-05-14 09:51:21

      java怎么对线程池做监控

      2025-05-14 09:51:15

      java动态获取实体类的字段

      2025-05-13 09:53:23

      查看更多

      热门文章

      Java线程同步synchronized wait notifyAll

      2023-04-18 14:15:05

      Java/Android Annotation注解/注入(二)

      2023-04-13 09:37:00

      Android/Java判断字符串String是否为float浮点数或double类型

      2023-04-17 09:39:54

      Java小数点数字和百分号数字之间的转换

      2023-04-13 09:48:57

      Java的自带注解Annotation(一)

      2023-05-10 06:02:06

      Java/Android Annotation注解/注入(三)

      2023-04-13 09:37:00

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      Java命令行编译打包

      Java中的数据结构与算法探秘

      Java静态方法块、非静态方法块、构造方法、静态方法执行顺序

      汇编语言教程及实例

      Java中Lambda表达式的应用

      Java中如何处理日期和时间?

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号