设计模式の建造者适配器桥接模式

文章目录

  • 前言
  • 一、建造者模式
  • 二、适配器模式
    • 2.1、对象适配器
    • 2.2、接口适配器
  • 三、桥接模式


前言

  本篇是关于设计模式中建造者模式、适配器模式(3种)、以及桥接模式的笔记。


一、建造者模式

  建造者模式是属于创建型设计模式,通过一步步构建一个复杂对象的方式,隐藏复杂的构造过程使得对象的创建过程更加灵活、易于扩展,同时不需要指定具体的构造方式。
  其组成部分有:

  • 产品:表示被建造的对象。
  • 抽象建造者:通常是抽象类或接口,定义了创建产品所需要的方法,由不同的子类去描述建造不同产品的具体步骤
  • 指挥者:组合了建造者对象,通常是将建造者对象作为其属性,提供方法控制建造的过程,指挥建造者完成特定的构建步骤。
  • 具体建造者:继承/实现抽象建造者,重写其中的方法,描述不同产品的建造步骤。

  为什么要使用建造者模式?我们可以看一个例子,假设现在需要建一所房子,用一个实体类封装房子的属性:

/*** 不管是 高层,洋房,还是别墅 都有 固定的这些属性*/
public class House {private String basic;private String wall;private String roof;public House() {}public House(String basic, String wall, String roof) {this.basic = basic;this.wall = wall;this.roof = roof;}//....get set 方法
}

  客户端直接完成对房子的创建,这样做很明显是存在弊端的。因为房子的种类有很多种,每一种的建造过程也是不一样的,虽然都包含一些共有的属性:

public class Client {public static void main(String[] args) {House house = new House();house.setBasic("打地基");house.setWall("砌墙");house.setRoof("盖屋顶");//--------如果有不同的房子要建立呢?---------------// 伪代码
//        if (type.equals("别墅")){
//            house.setBasic("打别墅的地基");
//            house.setWall("砌别墅的墙");
//            house.setRoof("盖别墅的屋顶");
//        }else {
//            house.setBasic("打高层的地基");
//            house.setWall("砌高层的墙");
//            house.setRoof("盖高层的屋顶");
//        }//--------如果后续对于工序还有不同的要求呢?---------------}
}

  使用建造者模式改进:

  1. 引入一个房子的建造者,定义了建不同房子都必须有的共有的工序:
/*** 房子的建造者*/
public abstract class CommonHouseBuilder {protected House house = new House();abstract void buildBasic();abstract void buildWalls();abstract void buildRoof();/*** 返回建造好的房子* @return*/public House getHouse() {return house;}}
  1. 具体的产品实现类,代表建立不同类型的房子:
public class HighRise extends CommonHouseBuilder{@Overridevoid buildBasic() {System.out.println("高层地基");}@Overridevoid buildWalls() {System.out.println("高层砌墙");}@Overridevoid buildRoof() {System.out.println("高层封顶");}
}
public class Villa extends CommonHouseBuilder{@Overridevoid buildBasic() {house.setBasic("别墅打基础");}@Overridevoid buildWalls() {house.setWall("别墅砌墙");}@Overridevoid buildRoof() {house.setRoof("别墅封顶");}
}
  1. 引入指挥者,指定建造的顺序:
/*** 建房子的指挥者*/
public class HouseBuildCommander {CommonHouseBuilder commonHouseBuilder;public HouseBuildCommander(CommonHouseBuilder commonHouseBuilder) {this.commonHouseBuilder = commonHouseBuilder;}public HouseBuildCommander() {}/*** 建造房子* @return*/public House constructHouse() {commonHouseBuilder.buildBasic();commonHouseBuilder.buildWalls();commonHouseBuilder.buildRoof();return commonHouseBuilder.getHouse();}}
  1. 客户端只需要让指挥者去指挥建造需要的房子即可:
public class Client {public static void main(String[] args) {//让指挥者 建造别墅HouseBuildCommander houseBuildCommander = new HouseBuildCommander(new Villa());House house = houseBuildCommander.constructHouse();System.out.println(house);}
}

House{basic = 别墅打基础, wall = 别墅砌墙, roof = 别墅封顶}

  从改造后的案例,不难看出,建造者模式,一般适用于产品建造过程有较多共同点的情况,例如上面的案例,无论是建别墅,高层也好,都需要经过打基础,砌墙,封顶的过程,只是不同的房子具体的工艺不一样。如果产品之间建造过程差异很大,比如建房子和建桥,那么就不适合使用建造者模式。并且建造者模式,和抽象工厂模式的区别在于,建造者模式注重创建产品的过程,而抽象工厂模式,强调的是通过提供一个统一的接口来创建这些产品系列,而不关心具体实现。

  • 如果你需要创建一组相关的产品,使用抽象工厂模式;
  • 如果你需要按步骤创建一个复杂对象,使用建造者模式。

二、适配器模式

  适配器模式是一种结构型设计模式,适用于一个类的接口转换成客户端希望的另一个接口。通过适配器模式,可以让原本因接口不兼容而无法一起工作的类协同工作。
  也可以用生活中的一个案例说明,例如有些笔记本电脑是支持直接插入网线的:
在这里插入图片描述  而有一些则没有网线接口,只有usb插槽,则需要在网线和usb插槽之间使用一个转接器
在这里插入图片描述  通过转接器,便可以实现有线上网的方式。这里的转接器就是适配器的体现(在网线和usb插槽之间作为缓冲层,对两者进行适配转换)。
  由此可知,适配器模式的主要角色有:

  1. 目标接口:客户端希望使用的接口。
  2. 源接口:需要被适配的接口,通常是一个现有的类或库,但它的接口与客户端不兼容。
  3. 适配器:实现目标接口的类,它将源接口转化为目标接口。

  如果体现在代码中,适配器模式分为类适配器对象适配器接口适配器三种体现,其中类适配器的适配器类,是使用继承被适配类,实现适配类的形式,不够灵活,所以不再记录。

2.1、对象适配器

  目前笔记本电脑有一个usb,无法直接插上网线:

public class Usb {public String outputUsb(){String type = "usb接口";System.out.println("向外提供"+type);return type;}
}

  网线接口:

public interface NetworkCable {String outputNetworkCable();
}

  通过适配器,使网线可以通过usb接口正常工作:

public class Adapt implements NetworkCable{private Usb usb;public Adapt(Usb usb) {this.usb = usb;}@Overridepublic String outputNetworkCable() {String usb = this.usb.outputUsb();System.out.println("将usb接口转接为网线接口");return "网线接口";}
}
public class Computer {public void connectInternet(NetworkCable networkCable){if (networkCable.outputNetworkCable().equals("网线接口")){System.out.println("连接互联网");}else {System.out.println("不能有线上网!");}}
}

  电脑的使用者,只需要在连接网络时,通过适配器连上电脑的usb接口,再将网线插到适配器上,即可实现有线上网:

public class Client {public static void main(String[] args) {Computer computer = new Computer();computer.connectInternet(new Adapt(new Usb()));}
}

2.2、接口适配器

  接口适配器,通常运用在某个具体的实现类,只想实现接口中部分方法的情况:
  接口中有五个方法:

public interface Inter {void method1();void method2();void method3();void method4();void method5();}

  但是某个实现类只想实现其中的部分方法,可以引入一个抽象类作为中间层,实现所有的方法:

public abstract class AbsClass implements Inter{@Overridepublic void method1() {}@Overridepublic void method2() {}@Overridepublic void method3() {}@Overridepublic void method5() {}@Overridepublic void method4() {}
}

  具体的实现类只需要继承抽象类即可自由选择需要实现的方法:

public class BusinessClass extends AbsClass{@Overridepublic void method1() {System.out.println("只用到了method1");}
}

三、桥接模式

  桥接模式是一种结构型设计模式,引入桥接对象来解耦抽象部分和具体实现部分,使抽象部分与实现部分分离。
  其主要角色有:

  1. 抽象类:定义了抽象的接口,并持有一个对实现类对象的引用。抽象类的实现通常依赖于实现类。
  2. 扩展抽象类:是抽象类的具体子类,提供了具体的功能实现。
  3. 实现类接口:定义了实现类的接口,通常是一个抽象类或者接口,提供了具体实现类的基本方法。
  4. 具体实现类:实现了实现类接口的具体类,负责实现具体的功能。

  如果举一个生活中的案例,例如手机有不同的款式,比如翻盖式,折叠式,不同的式样又有不同的品牌。假设需要新增一个样式,那么需要在新的样式下加上所有的品牌。(反之也一样,在所有的品牌下都加上新样式)。
  引入桥接模式解决这样的问题,则可以将品牌设置为一个接口,并定义所有品牌手机都具有的功能(开机,关机,打电话):

/*** 品牌* 所有品牌的手机都有开机关机,打电话的功能*/
public interface Brand {void open();void close();void call();
}

  不同品牌的手机实现品牌接口,重写其中的方法:

public class VivoPhone implements Brand {@Overridepublic void open() {System.out.println("vivo 手机 开机");}@Overridepublic void close() {System.out.println("vivo 手机 关机");}@Overridepublic void call() {System.out.println("vivo 手机 打电话");}
}
public class XiaomiPhone implements Brand{@Overridepublic void open() {System.out.println("小米手机 开机");}@Overridepublic void close() {System.out.println("小米手机 关机");}@Overridepublic void call() {System.out.println("小米手机 打电话");}
}

  将手机设置为抽象类,组合了品牌,同时引用了不同品牌共有的方法:

public abstract class Phone {private Brand brand;public Phone(Brand b) {this.brand = b;}public void open(){brand.open();}public void close(){brand.close();}public void call(){brand.call();}}

  不同样式的手机,只需要继承手机抽象类即可:

public class FoldedPhone extends Phone{public FoldedPhone(Brand b) {super(b);}@Overridepublic void open() {super.open();System.out.println("折叠式 手机开机");}@Overridepublic void close() {super.close();System.out.println("折叠式 手机关机");}@Overridepublic void call() {super.call();System.out.println("折叠式 手机打电话");}
}

  创建一个折叠式的小米手机:

public class Client {public static void main(String[] args) {FoldedPhone foldedPhone = new FoldedPhone(new XiaomiPhone());foldedPhone.call();foldedPhone.open();foldedPhone.close();}
}

小米手机 打电话
折叠式 手机打电话
小米手机 开机
折叠式 手机开机
小米手机 关机
折叠式 手机关机

  如果后续需要增加品牌或者样式,只需要实现品牌接口,或者继承手机抽象类即可。从这个案例不难看出,当一个系统有多个维度需要变化时,桥接模式可以把这些维度分开,避免创建大量的子类和多重继承


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/64091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能引导小车充电系统设计(论文+源码)

1总体方案设计 在16*16点阵LED字符显示器的设计中,系统总体框架如图2.4所示,包括单片机主控模复位电路模块、晶振电路模块、按键电路模块、LED点阵驱动电路模块,蓝牙模块等构成。系统功能实现主要是利用系统在软件程序编写过程中&#xff0c…

PCIe学习笔记

PCIE高速串行数据总线 当拿到一块板子 比如你要用到PCIE 首先要看这块板子的原理图 一般原理图写的是 PCI express 表示PCIE 以下是Netfpga为例下的PCIE插口元件原理图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/01dc604fbdc847e8998a978c83c7b2eb.png 一般主…

RabbitMQ实现消息发送接收——实战篇(路由模式)

本篇博文将带领大家一起学习rabbitMQ如何进行消息发送接收,我也是在写项目的时候边学边写,有不足的地方希望在评论区留下你的建议,我们一起讨论学习呀~ 需求背景 先说一下我的项目需求背景,社区之间可以进行物资借用&#xff0c…

The Past, Present and Future of Apache Flink

摘要:本文整理自阿里云开源大数据负责人王峰(莫问)在 Flink Forward Asia 2024上海站主论坛开场的分享,今年正值Flink开源项目诞生的第10周年,借此时机,王峰回顾了Flink在过去10年的发展历程以及 Flink社区…

城市大脑新型智慧城市数据中台建设方案

建设背景与现状 随着城市化进程的加速,城市数据呈现出爆炸式增长,但数据的整合、共享和利用却面临诸多挑战。信息孤岛、数据冗余、管理分散等问题日益突出,制约了智慧城市的发展。为了解决这些问题,构建城市大脑新型智慧城市数据…

力扣-图论-12【算法学习day.62】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…

每日一站技術架構解析之-cc手機桌布網

# 網站技術架構解析: ## 一、整體架構概述https://tw.ccwallpaper.com是一個提供手機壁紙、桌布免費下載的網站,其技術架構設計旨在實現高效的圖片資源管理與用戶訪問體驗優化。 ### (一)前端展示 1. **HTML/CSS/JavaScript基礎構…

代码随想录算法训练营第三十二天|动态规划理论基础|LC509.肥波那些数|LC70.爬楼梯|LC746.使用最小花费爬楼梯

动态规划理论基础 解释:动态规划,英文:Dynamic Programming,简称DP;如果某一问题有很多重叠子问题,使用动态规划是最有效的。 动态规划五部曲: 1、确定dp数组(dp table)…

RabbitMQ Work Queues (工作队列模式) 使用案例

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:RabbitMQ 📚本系列文章为个人学…

【安卓开发】【Android Studio】启动时报错“Unable to access Android SDK add-on list”

一、问题描述 在启动Android Studio时,软件报错:Unable to access Android SDK add-on list,报错截图如下: 二、原因及解决方法 初步推测是由于网络节点延迟,无法接入谷歌导致的。点击Cancel取消即可。

掌握线性回归:从简单模型到多项式模型的综合指南

目录 一、说明 二、简单线性回归 三、线性回归的评估指标 3.1 线性回归中的假设 四、从头开始的简单线性回归代码 五、多元线性回归 六、多元线性回归代码 七、多项式线性回归 八、多项式线性回归代码 九、应用单变量多项式回归 十、改变多项式的次数 十一、多列多项式回归 一、…

sqlmap详解

一.sqlmap -u URL --forms sqlmap -u http://192.168.11.136:1337//978345210/index.php --forms 针对特定的 URL 进行 SQL 注入测试,特别是针对表单(form)的 POST 注入 forms:这个参数告诉 sqlmap 解析并测试目标 URL 中的表单…

OBS + SRS:打造专业级直播环境的入门指南

OBS SRS:打造专业级直播环境的入门指南 1. OBS简介2. OBS核心功能详解2.1 场景(Scenes)管理2.2 源(Sources)控制2.3 混音器功能2.4 滤镜与特效2.5 直播控制面板 3. OBS推流到SRS服务器配置指南3.1 环境准备3.2 OBS推流…

Vue组件相关记录

Vue组件开发 非单文件组件 创建组件api Vue.extend({}) const student Vue.extend({template: <div>{{studentName}} - {{age}}</div>,data() {return {studentName: jjking,age: 12}}})new Vue({el: #app,//局部注册components: {student: student}})不能使用e…

【潜意识Java】深入理解 Java 面向对象编程(OOP)

目录 什么是面向对象编程&#xff08;OOP&#xff09;&#xff1f; 1. 封装&#xff08;Encapsulation&#xff09; Java 中的封装 2. 继承&#xff08;Inheritance&#xff09; Java 中的继承 3. 多态&#xff08;Polymorphism&#xff09; Java 中的多态 4. 抽象&…

【Linux SH脚本】LinuxCheck 应急检查信息脚本

LinuxCheck 1.下载地址 【Linux SH脚本】LinuxCheck 应急检查信息脚本 2.简介 LinuxCheck 是一个开源的自动化检查脚本&#xff0c;旨在快速检测 Linux 系统的安全配置和潜在问题。它支持多种发行版&#xff0c;能够扫描并生成详细的报告&#xff0c;涵盖用户管理、权限配置…

docker 部署 redis

docker 部署 redis 1. 下载 redis 镜像 # docker images | grep redis bitnami/redis 7.2.4-debian-11-r5 45de196aef7e 10 months ago 95.2MB2. docker-compose 部署 version: "3" services:redis:image: bitnami/redis:7.2.4-debian-11-…

相机测距原理

基础概念的回顾 焦距的定义 焦距是指透镜或镜头的光学中心&#xff08;通常是透镜的几何中心&#xff09;到其焦点的距离。 焦点是光线的交点&#xff0c;它指的是透镜或镜头聚焦所有入射光线后汇聚的位置。焦点的位置与透镜的曲率和光线的入射角度相关。就是说所有光线经过…

Python粉色圣诞树

系列文章 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…

数据分析学习Day1-使用matplotlib生成2小时每分钟的气温可视化分析图

注意&#xff1a;需要提前下载matplotlib包 pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple import matplotlib.pyplot as plt import random from matplotlib import font_manager # 数据准备 x list(range(121)) # 使用 list() 转换为列表 y [rando…