从重构的角度学习bridge设计模式

从音游FC到QT框架:拆解高难度Mod谱面与工程化开发 在游戏开发与音游社区中,框架化思维和模块化设计是提升项目可维护性和扩展性的核心。以QT框架为例,其信号与槽机制、跨平台特性为软件工程提供了稳定基础,而类似原理在游戏模组开发中同样关键。通过分析高难度谱面设计,我们可以理解其背后的算法逻辑,如节奏密度突变、键位排列模式等,这本质上是将视觉信息转化为精确时序输入的工程问题。在技术实现层面,使用类似“Rewired”的输入管理系统或QT框架重构游戏,能够优化输入延迟、增强模块解耦,从而提升游戏体验的稳定性和可定制性。这种从游玩到开发的过程,体现了从消费内容到创造内 阅读详情
从重构的角度学习bridge设计模式

Bridge模式是一个在实际系统中经常应用的模式。它最能体现设计模式的原则
针对接口进行编程,和使用聚合不使用继承这两个原则。


由于我们过分的使用继承,使类的结构过于复杂,不易理解,难以维护。特别
是在Java中由于不能同时继承多个类,这样就会造成多层继承,维护更难。
Bridge模式是解决多层继承的根本原因。如果你在实现应用中一个类,需要继承
两个以上的类,并且这两者之间又持有某种关系,它们两个都会有多种变化。
Bridge模式是把这两个类,分解为一个抽象,一个实现,使它们两个分离,这样
两种类可以独立的变化。
抽象就是,把一个实体的共同概念(相同的步骤),抽取出来(分解出几个相互独立的步骤),
作为一个过程。如我们把数据库的 操作抽象为一个过程,有几个步骤,创建SQL语句,
发送到数据库处理,取得结果。

实现就是怎样完成这个抽象步骤,如发送到数据库,需要结合具体的数据库,考虑怎样完成这个步骤等。
并且同一步骤可能存在不同的实现,如对不同的数据库需要不同的实现。

现在我们假设一个情况,也是WEB中经常遇到的,在一个page有输入框,
如客户信息的姓名,地址等,输入信息后,然后按查找按钮,把查找的结果显示出来。
我们现在假设查找客户信息和帐户信息,它们在不同的表中。
但是我们的系统面对两种人群,总部的它们信息保存到oracle数据库,但是各个分公司
的数据保存在Sybase中,数据库的位置等各不相同,这两种的操作不同。

下面是我们一般首先会使用的方式,使用if else进行,判断,这样使用系统
难以维护,难以扩展,不妨你增加一种查询,或者一种数据库试试????
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
String SQL="";
if(ActionType.equal("查找客户信息")){
//如果是查询客户信息,拼SQL语句从客户表中读取数据
SQL="select * from Customer "

if(dbType.equal("oracle")){
//从总部数据库读取,数据库为Oracle
String connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:HRDB";
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
Connection conn = DriverManager.getConnection (connect_string);
// Create a statement
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery (SQL);
//以下省略部分动态从数据库中取出数据,组装成Vector,返回
..................................
...................................
}else(dbType.equal("sybase")){
//从分公司数据库读取,数据库为Sybase
String connect_string ="jdbc:sybase:Tds:cai/cai@192.168.1.12:1521:FIN";
DriverManager.registerDriver (new com.sybase.jdbc.SybDriver());
Connection conn = DriverManager.getConnection (connect_string);
// Create a statement
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery (SQL);
//以下省略部分动态从数据库中取出数据,组装成Vector,返回
..................................
...................................

}

}else if(ActionType.equal("查找帐户信息")){
//如果是查询帐户信息,拼接SQL语句从帐户表中读取数据
SQL="select * from Account "
if(dbType.equal("oracle")){
..........................
..........................
(作者注:此处省略从oracle读取,约300字)

}else if(dbType.equal("Sybase")){
..........................
..........................
(作者注:此处省略从Sybase读取,约300字)
}

}
}
}

如果你认为这写的比较弱智,应该进行使用函数,但是你也会大量使用if else.???

于是我们进行重构,首先我们学习过DAO模式,就是把数据读取进行分里,我们定义一个
共同的接口,它负责数据库的操作,然后根据不同的数据库进行实现,在我们的查询操作中,
使用接口,进行操作,这样就可以不用考虑具体的实现,我们只管实现过程。

查询共同接口:
public interface searchDB{
public Vector searchFromDB(String SQL)
}
Oracle数据库的查询实现
public class searchDBOracleImpl{
public Vector searchFromDB(String SQL){
//从总部数据库读取,数据库为Oracle
String connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:HRDB";
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());

ResultSet rset = stmt.executeQuery (SQL);
.............................
............................

}
}
Sybase数据库的查询实现
public class searchDBSysbaseImpl{
public Vector searchFromDB(String SQL){
//从分公司数据库读取,数据库为Sysbase
String connect_string ="jdbc:sybase:Tds:cai/cai@192.168.1.12:1521:FIN";
DriverManager.registerDriver (new com.sybase.jdbc.SybDriver());
ResultSet rset = stmt.executeQuery (SQL);
.............................
............................

}
}

这样在我们的查询中就可以使用接口searchDB,但是创建有是一个问题,因为我们不能
静态的确定,查询的数据库类型,必须动态确定,于是我们又想到使用简单工厂方法,
来分别创建这里的具体实现,根据类别,创建
public class searchFactory{
public static searchDB createSearch(int DBType){
if(DBType.equal("oracle")){
return searchDBOracleImpl();
}else if(DBType.equal("sybase")){
return searchDBSysbaseImpl();
}
}
}
于是我们的查询代码可以改变为这样了;
public class SearchAction(){

public Vector searchData(string ActionType,String DbType){
String SQL="";
if(ActionType.equal("查找客户信息")){
//如果是查询客户信息,拼SQL语句从客户表中读取数据
SQL="select * from Customer "
searchDB obj=searchFactory.createSearch(DbType);
return obj.searchFromDB(SQL);

}else if(ActionType.equal("查找帐户信息")){
//如果是查询帐户信息,拼接SQL语句从帐户表中读取数据
SQL="select * from Account "
searchDB obj=searchFactory.createSearch(DbType);
return obj.searchFromDB(SQL);
}
}
}
是不是简单一些,如果增加一个新的数据库,对我们只需增加一个新的数据库实现便可,
老的代码,不需改变,这样便实现开-闭原则(Open-closed原则),在我们的查询查询
中使用的是接口,这就是设计模式的原则,针对接口进行编程,并且使用聚合,而不是直接的继承
大家,可以考虑使用继承来完成该工作怎样实现?????

上面是把实现进行分离,实现可以动态变化!!!!!

我们把查询的操作的具体数据库实现进行了分离,增强了灵活性,但是我们的查询。
仍然使用了if else这样仍然不易进行扩展,于是我们进行抽象一个查询操作的过程,
把它分成几个具体步骤,创建SQL语句,发送到数据库,执行查询,返回结果。
它们虽然是不同的查询,SQL各不相同,不同数据库执行不同,返回结果的内容不同。但是
这个过程却是不变的,于是我们声明一个抽象类,来完成这个过程。

public abstract class searchAction{
searchDB obj;
//两个步骤
public searchDB createSearchImple(int DbType){
return searchFactory.createSearch(DbType);
}
public abstract String createSQL();

//查询过程,最后返回结果
public vector searchResult(int DbType){
obj=createSearchImple(DbType);
return obj.searchFromDB(createSQL())
}
}

//我们客户查询,操作
public class searchCustomerAction{
public String createSQL(){
return "select * from Customer"
}
}
//我们的帐户查询操作
public class searchAccountAction{
public String createSQL(){
return "select * from account"
}
}

这样我们的查询编程简单的创建SQL语句,我们应该再创建一个工厂方法,
来完成创建它们
public class actionFactory{
public static searchAction ceateAction(int actionType){
if(actionType.equal("customer")){
return searchCustomerAction();
}else if(actionType.equal("account")){
return searchAccountAction();
}
}
}
这样我们把查询操作的过程进行了抽象,定义了步骤,和具体过程,经过我们的两次改变
把抽象部分和实现部分进行分离,使他们都可以独立的变化,增强灵活性。
我们再看当初查询实现,现在经过这两次的地修改,变成了什么模样?如下:

public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
searchAction action=actionFactory.ceateAction(ActionType);
return action.searchResult(DbType);
}
现在假如增加一个数据库类型,将会改变那些??,如果增加一种查询操作需要改变那些???

讨论点:
1:在我们的重构过程中,
怎样使用设计模式原则的???
现在如果增加功能,遵循开闭原则吗??
2:我们使用了两个简单工厂,这是为了简化,一般最好使用抽象工厂方法,
如果改为抽象工厂,怎样修改???



我打算写一系列的文章介绍设计模式,
希望从重构的角度考虑模式的应用,而不是
直接介绍模式,这样对初学者容易入门,step by step。
如果在自己的代码中遇到类似的情景,可以进行重构。


从重构学习proxy,预告
为什么EJB有Home,remote,bean这三种角色?
为什么又客户端与容器进行交互??
介绍在EJB中的应用???

从重构学习decorator??
软件设计师(中级)概要笔记:基于软件设计师教程(第5版) 软件设计师(中级)笔记:基于软件设计师教程(第5版) 阅读详情

相关推荐

告别手绘!用Aseprite+Unity Tilemap,从AI生成到2D游戏地图的保姆级搭建流程

本文详细介绍了如何利用Aseprite和Unity Tilemap从AI生成素材到搭建2D游戏地图的完整流程。涵盖AI生成素材的预处理、图层管理、动画制作,以及Unity中的Tilemap系统配置和性能优化技巧,帮助开发者高效创建像素风游戏地图。

weixin_29015483的博客 582

桥接模式(Bridge模式)详解

在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于 Photoshop 这样的软件,能画不同形状和不同颜色的图形呢?如果用继承方式,m 种形状和 n 种颜色的图形就有 m×n 种,不但对应的子类很多,而且扩展困难。 当然,这样的例子还有很多,如不同颜色和字体的文字、不同品牌和功率的汽车、不同性别和职业的男女、支持不同平台和不同文件格式的媒体播放器等。如果...

u012045045的博客 6716

别再死记硬背GNN公式了!用PyTorch Geometric从零实现一个GraphSAGE(附完整代码)

本文通过PyTorch Geometric从零实现GraphSAGE模型,深入解析图神经网络的核心原理与实战应用。文章提供完整代码示例,涵盖环境配置、邻居采样、信息聚合等关键步骤,帮助开发者掌握图表示学习技术,避免陷入公式推导的困境。适合希望将GNN应用于实际项目的中级开发者和学生。

weixin_42530570的博客 346

Bridge Pattern

文章目录Bridge Pattern使用范围 Bridge Pattern 一张图来展示 使用范围 将接口定义和实现分离 接口定义和实现分辨独立扩展 用户端对实现端的代码修改无感知 对用户端屏蔽实现部分 多个对象之间共享实现部分 ...

creambean的博客 221

KBS投稿全流程拆解:从模板准备到条件接收的实战指南

本文详细拆解了KBS期刊投稿的全流程,从模板准备、投稿系统操作到返修策略和条件接收。重点介绍了Cover Letter撰写技巧、Latex模板选择、审稿周期管理以及返修文件的系统准备方法,帮助研究者高效完成KBS投稿并提升接收概率。

weixin_26938645的博客 703

阿里开源最强数字人工具 EchoMimicV2,本地部署(一)

EchoMimicV2是阿里推出的半身人体AI数字人项目,基于参考图片、音频剪辑和手部姿势序列生成高质量动画视频,确保音频内容与半身动作的一致性。现在本地部署,安装体验一下。

缘分天空的专栏 4614

设计模式学习笔记--桥梁(Bridge)模式

桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)解耦,使得二者可以独立地变化”。桥梁模式的目的是为了降低耦合。

Java之旅 1791

信贷风控分析—征信数据源

详解企业和个人征信报告,以及信贷风控之指标构造案例参考

csdnbt的博客 3628

设计模式笔记—1_TemplateMethod

文章目录GOF-23模式分类从目的看从范围看从封装变化角度对模式分类组件协作单一职责对象创建对象性能接口隔离状态变化数据结构行为变化领域问题重构获得模式 Refactoring to Patterns重构关键技法组件协作模式Template Method动机定义代码对比结构化软件设计流程Library开发库template1_lib.cppApplication应用程序开发template1_ap...

Felix_hyfy的博客 283

【WRF-Chem】预处理工具(Preprocessors)总结

预处理工具(Preprocessors)总结

WW、forever的博客 1179

效果炸裂_安装midscene_copw基于midscene操作电脑_基于视觉的软件测试执行_MIDSCENE的安装和使用---AI大模型应用探索0012

摘要:本文介绍了如何通过安装MidSceneJS来增强Copaw的屏幕操作能力。首先需要安装Node.js和npm,并配置淘宝镜像源加速安装。然后全局安装MidScene CLI工具(npm install @midscene/cli -g)。接着配置视觉大模型服务,通过设置环境变量指定模型API密钥、名称、基础URL和家族类型(如qwen3.5-27b),配置文件需存放在C:\Users\Administrator.copaw目录。安装成功后,MidScene已能成功识别并操作屏幕,使用效果良好。文中还提

添柴程序猿的专栏 639

设计模式的征途—8.桥接(Bridge)模式

在现实生活中,我们常常会用到两种或多种类型的笔,比如毛笔和蜡笔。假设我们需要大、中、小三种类型的画笔来绘制12中不同的颜色,如果我们使用蜡笔,需要准备3*12=36支。但如果使用毛笔的话,只需要提供3种型号的毛笔,外加12个颜料盒即可,涉及的对象个数仅为3+12=15,远远小于36却能实现与36支蜡笔同样的功能。如果需要新增一种画笔,并且同样需要12种颜色,那么蜡笔需要增加12支,而毛笔却只需要新...

weixin_33816821的博客 164

视觉Transformer实战 | Data-efficient image Transformer(DeiT)详解与实现

在计算机视觉领域,Vision Transformer (ViT) 已经证明了纯 Transformer 架构在图像分类任务上的强大能力。然而,ViT 通常需要在大规模数据集上预训练才能达到最佳性能,DeiT (Data-efficient image Transformer) 通过引入一系列训练策略和优化,使得 Transformer 模型能够在相对较小的数据集上取得优异表现。本节将详细介绍 DeiT 的技术原理,并使用 PyTorch 从零开始实现 DeiT 模型。

盼小辉丶的博客 1341

设计模式 - 结构型模式总结

我们介绍完了所有GOF设计模式书上的7种结构型设计模式,又到了总结的时候了。 如果回顾一下这7种结构型设计模式,我们会发现有些模式很类似。是的,从结构来看确实很像。但是我们讲设计模式很多时候是从设计者的意图来区分的,单从代码结构来看可能是很类似,但是意图完全不一样。   Adapter,Bridge,Facade Adapter:目的是为了解决不同接口类库之间不能一起工作的问题。Adapt

zj510的专栏 800

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

BRIDGE(桥接)—对象结构型模式

桥接模式【bridge】 什么是桥接模式 将抽象部分于它的实现部分分离,使它们都可以独立地变化,这个摘自<设计模式>的解释,一般很难去理解,稍后我会以代码加文字的形式给大家解释清楚。 什么场景会用到桥接模式 现在给大家一个场景,比如现在要做这样一个功能,需求上描述,分别开发多个软件应用,同时需要适应不同的手机型号,再详细一点,比如,现在开发了一款购物app和阅读app,需要兼容...

bas_ball的专栏 333

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

设计模式三重天[之二]

写作背景:        一直在看关于设计模式的书并不断的实际工作中努力实践,同时也看到了播客园上设计模式团队文章热火朝天的研究和讨论。心里非常高兴,在国内设计模式的研究和使用还不是很丰富和完善的今天,这种讨论无疑会对每个园中的个体还是播客园整体实体的提升有着重大的意义,我非常希望以后想研究.NET程序的人只要知道两个网址就能完成工作中90% 的知识查询,一个是微软的MSDN,一个就是播客园。...

weixin_34289744的博客 69

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

3个核心技巧:在Neovim中开启AI编程新纪元

你是否曾面对复杂代码库感到困惑?是否希望有个编程伙伴能实时解释代码逻辑?opencode.nvim正是为Neovim开发者打造的AI助手插件,它无缝连接OpenCode AI,让你在熟悉的编辑环境中获得智能编程支持。通过实验性LSP功能,这个插件将AI能力深度集成到Neovim工作流中,提供悬停解释、诊断修复等实用功能,让编程变得更加高效直观。 ## 一、AI编程助手的3种核心应用场景 ###

gitblog_00789的博客 435

Python 学习 ---> 模块、pypi ( 模块库 )、添加模块路径

什么是 模块 在 Python 中,一个.py文件就是一个模块(Module)。模块的名字就是文件的名字。在模块内部,通过全局变量__name__可以获取模块名(即字符串) 模块作用 为了实现代码的复用,通常会把一些其他程序中重用的代码拿出来单独放在一个程序文件中,

freeking101的博客 3483

软考-系统分析师-备考笔记

根据学习视频和一些资料整理的软考系统分析师考试笔记,2025年下半年通关

提子同学是我 1027

文具办公用品管理系统基于HarmonyOS API 24实战解析:“接口描述静态数据形状、@Observed 类承载动态数据行为“的设计模式,是 ArkTS 应用中处理复杂数据对象的最佳实践

在 HarmonyOS NEXT 正式商用的背景下,ArkTS 作为鸿蒙生态的官方应用开发语言,正在从传统的命令式 UI 开发范式向声明式 UI 范式全面迁移。ArkUI 框架以组件化、声明式、状态驱动为核心特征,要求开发者以"描述 UI 应该是什么样"而非"一步步操作 UI 怎么变"的思维方式构建界面。

2401_86031952的博客 469

Ubuntu 22.04安装ROS1:三种方案、核心挑战与迁移指南

ROS(Robot Operating System)作为机器人开发的主流框架,其核心价值在于提供了硬件抽象、底层设备控制、进程间通信等通用服务,极大简化了复杂机器人系统的构建。其通信机制基于节点、话题、服务等概念,实现了模块化与分布式计算。在工程实践中,环境配置与系统兼容性是开发者面临的首要挑战,尤其是在操作系统版本与ROS发行版生命周期不同步的情况下。Ubuntu 22.04作为长期支持版本,其默认的Python 3.10和更新的系统库(如OpenCV)与ROS1的官方环境存在差异,这直接导致了依赖管理

axfcjwkbi259888707的博客 955

基于HarmonyOS API 24实战解析Blank() 组件自动填充标题栏中剩余的空白空间,通过 Row 的 alignItems(VerticalAlign.Center) 实现垂直居中对齐

健身管理类应用与之前分析的外卖、招聘等应用有本质差异——它的核心数据不是"交易"或"任务",而是"时间序列的身体状态数据":每次训练有时长、卡路里、组数、重量;每次饮食有热量、蛋白质、碳水、脂肪;每周有运动时长趋势图。这些数据的共同特征是"随时间积累,用户需要横向对比和趋势分析"。这导致健身App的数据层设计必须从第一天就考虑"历史数据查询"和"多维度聚合"的需求,而非仅关注当前单条记录的增删改查。健身应用的用户行为模式也有独特之处:用户使用健身App的目标是"坚持",而不是"一次性完成任务"。这意味着激励

2401_86031952的博客 205

基于HarmonyOS API 24实战解析养车记录应用textOverflow({ overflow: TextOverflow.Ellipsis }) 配合 maxLines(1) 是实现文字溢出

健身管理类应用与之前分析的外卖、招聘等应用有本质差异——它的核心数据不是"交易"或"任务",而是"时间序列的身体状态数据":每次训练有时长、卡路里、组数、重量;每次饮食有热量、蛋白质、碳水、脂肪;每周有运动时长趋势图。这些数据的共同特征是"随时间积累,用户需要横向对比和趋势分析"。这导致健身App的数据层设计必须从第一天就考虑"历史数据查询"和"多维度聚合"的需求,而非仅关注当前单条记录的增删改查。健身应用的用户行为模式也有独特之处:用户使用健身App的目标是"坚持",而不是"一次性完成任务"。这意味着激励

2401_86031952的博客 145
下一篇: 如何迅速成为Java高手
jstml
博客等级 码龄26年 1粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值