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

软件设计模式(二):工厂、门面、调停者和装饰器模式

前言

        在这篇文章中,荔枝将会梳理软件设计模式中的四种:工厂模式、Facade模式、Mediator模式和装饰器Decorator模式。其中比较重要的就是工厂模式和装饰器模式,工厂模式在开发中使用的频数比较高。希望荔枝的这篇文章能讲清楚哈哈哈哈,希望能帮助到有需要的小伙伴~~~


文章目录

前言

一、工厂模式

1.1 简单工厂

1.2 工厂方法

1.3 抽象工厂

二、调停者模式和门面模式

2.1 门面模式Facade

2.2 调停者模式Mediator

三、装饰器模式Decorator 

总结


一、工厂模式

1.1 简单工厂

首先定义一个交通工具的工厂函数接口Moveable。

package com.crj.factorymethod;
/*** 工厂函数接口*/
public interface Moveable {void go();
}

 我们要实现某一种方式的交通工具就需要通过将该交通工具类实现该接口并重写go方法。

package com.crj.factorymethod;/*** Car类继承工厂函数接口*/
public class Car implements  Moveable {public void go() {System.out.println("Car go wuwuwuwuw....");}
}

通过简单工厂模式来返回实例化后的交通工具对象。

package com.crj.factorymethod;/*** 简单工厂模式* 简单工厂的可扩展性不好*/
public class SimpleVehicleFactory {public Car createCar() {//before processingreturn new Car();}public Broom createBroom() {return new Broom();}
}

1.2 工厂方法

        上文中可以看出,简单工厂模式的可扩展性比较差,但我们需要新创建一种交通方式的时候就需要重新在工厂SimpleVehicleFactory定义并写死相应的对象方法,这在后期的时候并不容易维护。那么还可以通过不同交通工具各自有一个工厂,方法类型都是继承自Moveable,返回值也是Moveable类型。

package com.crj.factorymethod;/*** 工厂方法*/
public class CarFactory {public Moveable create() {System.out.println("a car created!");return new Car();}
}

main方法

package com.crj.factorymethod;public class Main {public static void main(String[] args) {Moveable m = new CarFactory().create();m.go();}
}

1.3 抽象工厂

前面我们已经把产品的构建和工厂一一对应了,但是我们操作起产品簇还不是很方便,我们可以通过抽象工厂直接操作创建一整个产品簇。在实现创建产品簇之前,我们需要创建抽象产品类、抽象工厂、具体产品类和具体的工厂。

抽象产品类

首先定义一些抽象产品类,并定义相应的抽象方法。

抽象工厂AbstractFactory

抽象工厂定义抽象的方法用于创建相应的产品簇中的类型产品。 

package com.mashibing.dp.abstractfactory;public abstract class AbastractFactory {abstract Food createFood();abstract Vehicle createVehicle();abstract Weapon createWeapon();
}

具体工厂类

具体工厂类继承自抽象工厂类,并重写不同类型的产品创建产品的方法。 

具体产品类

具体的产品类继承自抽象产品类

main文件

        在main文件中我们通过实例化具体产品类得到对象并调用相应的产品创建方法首先产品簇的创建。可以看到在这段demo中我们即使需要得到不同的产品簇,也仅需要通过实例化不同的工厂类即可。

package com.mashibing.dp.abstractfactory;public class Main {public static void main(String[] args) {AbastractFactory f = new ModernFactory();Vehicle c = f.createVehicle();c.go();Weapon w = f.createWeapon();w.shoot();Food b = f.createFood();b.printName();}
}

具体的逻辑可以看一下这张图,荔枝感觉还是没讲得很清楚,剩下三分自己就得靠大家聪明得脑瓜啦。


二、调停者模式和门面模式

2.1 门面模式Facade

        门面模式要求一个系统外部与其内部的通信必须通过一个统一的对象进行,通过一个高层次的接口管理外部通信与内部对象簇之间的通信,简单理解就是一个中介(门面),外部仅需要跟这个中介对接即可,中介再委派客户端发送的请求到相应的子系统中,这也是一种黑箱操作。在该模式下可以同时拥有一个或者多个系统,每个系统是一个类的集合,同时系统对于门面只是当成客户端来处理。

需要注意的是:

  • 一个系统可以有多个门面

  • 门面不参与系统内的业务逻辑

2.2 调停者模式Mediator

        调停者模式相当于一个星型连接,该模式多用于消息中间件如MQ中,对象间只需要跟中间人进行沟通即可,由中间人进行消息的收发和处理,是一种解耦的操作。对于门面模式和调停者模式的区别详情可以下图,二者其实区别并不大并且在某些场景下是可以互换的。


三、装饰器模式Decorator 

装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些功能的模式,它属于对象结构型模式。

优点:

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则

缺点:装饰器模式会增加许多子类,过度使用会增加程序复杂性。

大致看了一些概念性的东西大机器是不是感觉不是特别具象,下面我们可以通过一个例子来理解一下装饰器模式具体是一个怎样的软件设计模式。 

package com.crj.Decorator;public class Decorator {/*** 装饰器模式* 使用实体装饰类装饰* @param args*/public static void main(String[] args) {A a = new A();B b = new B();RedShapeDecorator rda = new RedShapeDecorator(a);rda.draw();BlueShapeDecorator rdb = new BlueShapeDecorator(b);rdb.draw();}
}/*** 接口*/
interface Shape{void draw();
}/*** 接口实现类*/
class A implements Shape{@Overridepublic void draw() {System.out.println("这是A类");}
}
class B implements  Shape{@Overridepublic void draw() {System.out.println("这是B类");}
}/*** 抽象装饰类*/
abstract class ShapeDecorator implements Shape{protected Shape decoratedShape;public ShapeDecorator(Shape decoratedShape) {this.decoratedShape = decoratedShape;}@Overridepublic void draw() {decoratedShape.draw();}
}/*** 第一个实体装饰类*/
class RedShapeDecorator extends ShapeDecorator{public RedShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {super.draw();setRedShapeDecorator(decoratedShape);}private void setRedShapeDecorator(Shape decoratedShape){System.out.println("Red");}
}
/*** 第二个实体装饰类*/
class BlueShapeDecorator extends ShapeDecorator{public BlueShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {super.draw();setRedShapeDecorator(decoratedShape);}private void setRedShapeDecorator(Shape decoratedShape){System.out.println("Blue");}
}

        在上面的demo中,我们定义了一个普通接口、两个基本的接口实现类、一个抽象装饰类和两个实体装饰类。接口实现类和抽象装饰类都实现了接口的实现方法并重写接口的方法。实体装饰类继承自抽象装饰类,由于抽象装饰类中含有有参构造方法,因此需要使用super关键字声明继承对象。我们通过往实体装饰类对象中传入一个实体类对象,实现了对对象调用的draw()方法的装饰。

        可以看一下这张图,我们可以发现其实在Shape接口上我们定义了一个ShapeDecorator抽象装饰类来装饰,所谓装饰其实也是增加功能。在前面中我们也提及装饰的本质就是使用抽象类继承接口,再使用具体的实现类装饰上功能,这种方式极好的解决了子类爆炸的问题。


总结

        到现在荔枝也梳理了几种设计模式了,总结一下自己的学习方法:主要是根据文档和大佬视频资源讲解梳理的,再自己手敲示例实现一遍,收获和体会确实是挺大的。学习设计模式可能会比较枯燥,大家加油,荔枝要继续前行咯~

今朝已然成为过去,明日依然向往未来!我是小荔枝,在技术成长的路上与你相伴,码文不易,麻烦举起小爪爪点个赞吧哈哈哈~~~ 比心心♥~~~

相关文章:

软件设计模式(二):工厂、门面、调停者和装饰器模式

前言 在这篇文章中,荔枝将会梳理软件设计模式中的四种:工厂模式、Facade模式、Mediator模式和装饰器Decorator模式。其中比较重要的就是工厂模式和装饰器模式,工厂模式在开发中使用的频数比较高。希望荔枝的这篇文章能讲清楚哈哈哈哈&#xf…...

pdf文件签名的问题解决

今天解决冲突的jar&#xff0c;结果出现下面的问题 java.lang.IllegalAccessError: tried to access method org.bouncycastle.asn1.DERNull.<init>()V from class com.itextpdf.text.pdf.security.PdfPKCS7at com.itextpdf.text.pdf.security.PdfPKCS7.getEncodedPKCS7…...

Node.js安装使用

目录 一、安装 Node.js二、环境变量配置三、npm常用命令 Node.js 是一个强大的运行时环境&#xff0c;它使您能够在服务器端运行 JavaScript 代码。它非常流行&#xff0c;用于构建 Web 应用程序、API 和各种后端服务。 一、安装 Node.js 1、访问 Node.js 官方网站。 在主页上…...

sql:SQL优化知识点记录(七)

&#xff08;1&#xff09;索引优化5 &#xff08;2&#xff09;索引优化6 &#xff08;3&#xff09;索引优化7 查询*&#xff0c; 百分号加右边&#xff0c;否则索引会失效 没建立索引之前都是全表扫描 没建立索引 建立索引&#xff1a; 建立索引 id是主键&#xff0c;他也…...

机器学习:基于梯度下降算法的线性拟合实现和原理解析

机器学习&#xff1a;基于梯度下降算法的线性拟合实现和原理解析 线性拟合梯度下降算法步骤算法实现数据可视化&#xff08;动态展示&#xff09;应用示例 当我们需要寻找数据中的趋势、模式或关系时&#xff0c;线性拟合和梯度下降是两个强大的工具。这两个概念在统计学、机器…...

关键点数据增强

1.关键点数据增强 # 关键点数据增强 from PIL import Image, ImageDraw import random import json from pathlib import Path# 创建一个黑色背景图像 width, height 5000, 5000 # 图像宽度和高度 background_color (0, 0, 0) # 黑色填充# 随机分布图像 num_images 1 # …...

最小化安装移动云大云操作系统--BCLinux-for-Euler-22.10-everything-x86_64-230316版

CentOS 结束技术支持&#xff0c;转为RHEL的前置stream版本后&#xff0c;国内开源Linux服务器OS生态转向了开源龙蜥和开源欧拉两大开源社区&#xff0c;对应衍生出了一系列商用Linux服务器系统。BCLinux-for-Euler-22.10是中国移动基于开源欧拉操作系统22.03社区版本深度定制的…...

003传统图机器学习、图特征工程

文章目录 一. 人工特征工程、连接特征二. 在节点层面对连接特征进行特征提取三. 在连接层面对连接特征进行特征提取四. 在全图层面对连接特征进行特征提取 一. 人工特征工程、连接特征 节点、连接、子图、全图都有各自的属性特征&#xff0c; 属性特征一般是多模态的。除属性特…...

Apache Tomcat 漏洞复现

文章目录 Apache Tomcat 漏洞复现1. Tomcat7 弱密码和后端 Getshell 漏洞1.1 漏洞描述1.2 漏洞复现1.3 漏洞利用1.3.1 jsp小马1.3.2 jsp大马 1.4 安全加固 2. Aapache Tomcat AJP任意文件读取/包含漏洞2.1 漏洞描述2.1 漏洞复现2.2 漏洞利用工具2.4 修复建议 3. 通过 PUT 方法的…...

Oracle-常用权限-完整版

-- 创建用户 create user TCK identified by oracle; -- 赋权 grant connect,resource to TCK; -- 删除权限 revoke select any table from TCK -- 删除用户 CASCADE(用户下的数据级联删除) drop user TCK CASCADE -- 查询权限列表 select * from user_role_privs; select * fr…...

jenkins 发布job切换不同的jdk版本/ maven版本

1. 技术要求 因为有个新的项目需要使用jdk17 而旧的项目需要jdk1.8 这就需要jenkins在发布项目的时候可以指定jdk版本 2. 解决 jenkins全局工具配置页面 配置新的jdk 路径 系统管理-> 全局工具配置 如上新增个jdk 名称叫 jdk-17 然后配置jdk-17的根路径即可&#xff08;这…...

如何在小程序中给会员设置备注

给会员设置备注是一项非常有用的功能&#xff0c;它可以帮助商家更好地管理和了解自己的会员。下面是一个简单的教程&#xff0c;告诉商家如何在小程序中给会员设置备注。 1. 找到指定的会员卡。在管理员后台->会员管理处&#xff0c;找到需要设置备注的会员卡。也支持对会…...

PaddleOCR学习笔记2-初步识别服务

今天初步实现了网页&#xff0c;上传图片&#xff0c;识别显示结果到页面的服务。后续再完善。 采用flask paddleocr bootstrap快速搭建OCR识别服务。 代码结构如下&#xff1a; 模板页面代码文件如下&#xff1a; upload.html : <!DOCTYPE html> <html> <…...

【Opencv】Pyhton 播放上一帧,下一帧,存video,逐帧分析

文章目录 读取具体哪一帧等待按钮写入解码方式与文件格式对应全部代码 读取具体哪一帧 这个方法可以获取某一帧&#xff1a; while True:cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)ret, frame cap.read()if not ret:break等待按钮 这个方法可以显示当前帧&#xff0c…...

【关于Java:认识异常】

文章目录 一、1. 异常概念与体系结构1.1 异常的概念1.2 常见的异常1.算数异常2.数组越界异常3.空指针异常 1.3 异常的体系结构1.4 异常的分类1. 编译时异常2. 运行时异常&#xff08;RuntimeException&#xff09; 二、 异常的处理方式2.1 防御式编程2.2 EAFP:&#xff08;异常…...

【C++ • STL • 力扣】详解string相关OJ

文章目录 1、仅仅翻转字母2、字符串中的第一个唯一字符3、字符串里最后一个单词的长度4、验证一个字符串是否是回文5、字符串相加总结 ヾ(๑╹◡╹)&#xff89;" 人总要为过去的懒惰而付出代价 ヾ(๑╹◡╹)&#xff89;" 1、仅仅翻转字母 力扣链接 代码1展示&…...

【Tomcat服务部署及优化】

Tomcat 一、什么是Tomcat?二、Tomcat 核心组件2.1 Tomcat 组件2.3 Container组件的结构2.4 Tomcat 请求过程 三、Tomcat 部署3.1 安装JDK3.2 设置JDK环境变量3.3 安装Tomcat并用supervisor启动解压添加到supervisord服务测试能否通过supervisorctl启动 四、Tomcat的端口和主要…...

C++之红黑树

红黑树 红黑树的概念红黑树的性质红黑树结点的定义红黑树的插入红黑树的验证红黑树与AVL树的比较 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上…...

Go语言网络编程(socket编程)TCP

1、TCP编程 1.1.1 Go语言实现TCP通信 TCP协议 TCP/IP(Transmission Control Protocol/Internet Protocol) 即传输控制协议/网间协议&#xff0c;是一种面向连接&#xff08;连接导向&#xff09;的、可靠的、基于字节流的传输层&#xff08;Transport layer&#xff09;通信协…...

C语言——局部和全局变量

局部变量 定义在函数内部的变量称为局部变量&#xff08;Local Variable&#xff09; 局部变量的作用域(作用范围)仅限于函数内部&#xff0c; 离开该函数后是无效的 离开该函数后&#xff0c;局部变量自动释放 示例代码&#xff1a; #include <stdio.h>// 函数定义 …...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

算法—栈系列

一&#xff1a;删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

构建Docker镜像的Dockerfile文件详解

文章目录 前言Dockerfile 案例docker build1. 基本构建2. 指定 Dockerfile 路径3. 设置构建时变量4. 不使用缓存5. 删除中间容器6. 拉取最新基础镜像7. 静默输出完整示例 docker runDockerFile 入门syntax指定构造器FROM基础镜像RUN命令注释COPY复制ENV设置环境变量EXPOSE暴露端…...

简单聊下阿里云DNS劫持事件

阿里云域名被DNS劫持事件 事件总结 根据ICANN规则&#xff0c;域名注册商&#xff08;Verisign&#xff09;认定aliyuncs.com域名下的部分网站被用于非法活动&#xff08;如传播恶意软件&#xff09;&#xff1b;顶级域名DNS服务器将aliyuncs.com域名的DNS记录统一解析到shado…...

多模态学习路线(2)——DL基础系列

目录 前言 一、归一化 1. Layer Normalization (LN) 2. Batch Normalization (BN) 3. Instance Normalization (IN) 4. Group Normalization (GN) 5. Root Mean Square Normalization&#xff08;RMSNorm&#xff09; 二、激活函数 1. Sigmoid激活函数&#xff08;二分类&…...

本地部署drawDB结合内网穿透技术实现数据库远程管控方案

文章目录 前言1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 前言 在数字化浪潮席卷全球的背景下&#xff0c;数据治理能力正日益成为构建现代企业核心竞争力的关键因素。无论是全球500强企业的数据中枢系统&#xff0c;还是初创…...