敏捷软件开发 - 原则、模式与实践 —— 设计模式(十一)VISITOR模式

速读《effective go》 effective go官方文档中文精简版 阅读详情

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。

本文对应原书第28章

VISTOR模式系列允许在不更改现有层次结构的情况下向其中增加新方法。

该系列中的模式如下

  • VISITOR模式
  • ACYCLIC VISITOR模式
  • DECORATOR模式
  • EXTENSION ObJECT模式

VISITOR模式

图1
这个结构,可以通过增加新的ModemVisitor派生类来增加新的操作系统配置函数,而完全不用对Modem层次结构进行更改。所以,VISITOR模式使用ModemVisitor的派生类代替了Modem层次结构中的方法。

这之所以被称为双重分发是因为它涉及了两个多态分发。第一个分发是accept函数。该分发辨别出所调用的accept方法所属对象的类型。第二个分发是visit方法,它辨别出要执行的特定函数。这两个分发赋予了VISITOR模式非常快的执行速度。

VISITOR模式中的两次分发形成了一个功能矩阵。在Modem的例子中,矩阵的一条轴是不同类型的Modem。另一条轴是不同类型的操作系统。该矩阵的每个单元都被一项功能填充,该功能描绘了如何把特定的Modem初始化为可以在特定的操作系统中使用。

ACYCLIC VISITOR模式

如果程序中要更改的层次结构不需要经常地增加新的派生类,那么VISITOR模式工作的很好。但是,如果被访问层次结构非常不稳定,经常需要创建许多新的派生类,那么每当向被访问层次结构中增加一个新的派生类时,就必须要更改并且重新编译Visitor基类以及它的所有派生类。在C++中,情况甚至更糟。每当增加任何一个新的派生类时,整个被访问层次结构就必须要被重新编译、重新部署。

可以使用一个成为ACYCLIC VISITOR模式的变体来解决这个问题。该变体把Visitor基类变成退化的,从而解除了依赖环。这个类中没有任何方法意味着它没有依赖于被访问层次结构的派生类。

图2
由于转型需要花费大量的执行时间,并且这些时间是不可预测的,所以ACYCLIC VISITOR模式不适用于严格的实时系统。该模式的复杂性可能同样会使它不适用于其他的系统。但是,对于那些被访问的层次结构不稳定,并且增量编译比较重要的系统来说,该模式是一个不错的选择。

正像VISITOR模式创建了一个功能矩阵(一个轴是被访问的类型,另一个轴是要执行的功能)一样,ACYCLIC VISITOR模式创建了一个稀疏矩阵。访问者类不需要针对每一个被访问的派生类都实现visit函数。例如,如果Ernie Modem不可以配置在UNIX中,那么UnixModemConfigurator就不会实现ErnieVisitor接口。因此,ACYCLIC VISITOR模式允许我们忽略某些派生类和功能的组合。有时,这可能是一个有用的优点。

DECORATOR模式

另一个可以在不改变现有类层次结构的情况下向其中增加新方法的模式是DECORATOR模式。

图3
ModemDecorator子类的dial方法首先执行自己的特殊操作,然后委托调用它包含的Modem实例
的dial方法。

EXTENSION OBJECT模式

还有另外一种方法可以在不更改类层次结构的情况下向其中增加功能,那就是使用EXTENSION OBJECT模式。这个模式虽然比其他模式复杂一些,但是它也更强大、更灵活一些。层次结构中的每个对象都持有一个特定扩展对象(extension object)的列表。同时,每个对象也提供一个通过名字查找扩展对象的方法。扩展对象提供了操作原始层次结构对象的方法。

例如,再次假设我们有一个材料单系统。我们想让该层次结构中的每个对象都具有创建表示自身的XML的能力。我们可以把toXML方法放到层次结构中,但是这回违反SRP。我们不希望把有关XML的内容和有关BOM的内容放到同一个类中。虽然我们可以使用VISITOR模式来创建XML,但是这无法使我们把针对每种不同类型BOM对象的XML生成代码分离。在VISITOR模式中,针对每个BOM类的所有XML生成代码都会在同一个VISITOR对象中。

EXTENSION OBJECT模式提供了一个实现这个目标的优雅方案。下图展示了具有两个不同类型扩展对象的BOM层次结构。一种扩展对象把BOM对象转换成XML。另一个扩展对象把BOM对象转换成CSV。第一种扩展对象通过getExtension(“XML”)获得,第二种扩展对象通过getExtension(“CSV”)获得。图中< >表示一个标记接口(也就是没有任何方法的接口)。

图4

结论

VISITOR模式是由诱惑力的。在它们面前很容易会失去自制力。如果它们有用就去使用它们,但是请对它们的必要性保持健康的怀疑。通常,可以使用VISITOR模式解决的问题往往也可以使用更简单的方法解决。

完整内容请查看敏捷软件开发 - 原则、模式与实践系列

敏捷软件开发 - 原则、模式与实践 —— 敏捷开发(一) 本文对应原书第1章和第2章。 敏捷软件开发宣言 个体和交互 胜过 过程和工具 可以工作的软件 胜过 面面俱到的文档 客户合作 胜过 合同谈判 响应变化 胜过 遵循规则 敏捷开发原则 我们最优先要做的是通过尽早的、持续的交付有价值的软件来使客户满意 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势 经常性的交付可以工作的软件,交付的间隔可以从几周到几个月... 阅读详情

相关推荐

敏捷软件开发 - 原则、模式与实践 —— 设计模式(十)PROXY模式和STAIRWAY TO HEAVEN模式

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。 本文对应原书第26章 PROXY模式 PROXY模式具有一个非常大的好处:重要关系的分离。在上面的例子中,业务规则和数据库就被完全分开了。在那些把业务 规则和数据库实现分离显得非常重要的情况中,PROXY模式是很适用的。就此而言,PROXY模式可以用来分离业务规则和任何种类的实现问题。它可以用来防止业务规则被诸如:COM、COBRA、EJB...

feifeilb的博客 474

Object-C中继承 ,分类(category),扩展(extension)使用与区别

在对于框架封装的时封装的功能模块大多是通用模块,为了减少耦合和代码冗余对于一些项目里的个性需求功能一般不会封装。但这样会面临在项目实施中,部分功能无法实现或者实现起来很麻烦,这种情况下类的继承,扩展就可以方便的解决以上问题。同时在对同系统类做个性化定制的时候也有很好的效果。为此整理了一下继承,分类,扩展的使用方法。

DARKSang的专栏 1686

VS2019 C# MySQL 学生信息增删改查(一、增删)

VS2019 C# MySQL 学生信息增删改查 由于刚刚学习VS2019,入手的第一个例子是编写一个简单的增删改查。这里,我以学生信息为例,进行详细的过程描述以及代码实现。 一、 新建一个Windows窗体应用程序 1、创建新项目界面,如下图所示。 2、更改项目名称,当然不修改也可以。我这里的是“StudentInfoSystem”;项目存放位置路径根据自己需要进行更改;“将解决方案和项目放在同一目录中”前面的勾选框,选不选都可以;点击“创建”,如下图所示。 二、前期准备工作 1、将Form1属性中

青哥 1万+

软件设计模式——访问者模式(Visitor)

定义与结构访问者模式,顾名思义使用了这个模式后就可以在不修改已有程序结构的前提下,通过添加额外的“访问者”来完成对已有代码功能的提升。《设计模式》一书对于访问者模式给出的定义为:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。从定义可以看出结构对象是使用访问者模式必须条件,而且这个结构对象必须存在遍历自身各个对象的方法。这便类似于java 中

Jungle_hello的博客 889

Linux平台CCS安装配置完整示例

手把手讲解在Linux系统中完成CCS安装与环境配置的全过程,涵盖关键步骤与常见问题解决,是查找ccs安装教程时不可多得的实战指南。

weixin_42601134的博客 514

FPGA中参数化SPI接口设计与Verilog实现

SPI(串行外设接口)作为嵌入式系统的核心通信协议,通过全双工、高速率特性在FPGA与Flash、ADC等外设交互中占据重要地位。参数化设计通过抽象时钟极性、数据位宽等可配置维度,采用分层架构实现硬件复用,显著提升开发效率。Verilog实现需重点处理跨时钟域同步和可配置帧结构,结合AXI总线集成与UVM验证方法学,可构建适应工业控制、物联网网关等场景的高可靠SPI解决方案。

ciya3282的博客 1408

ACYCLIC VISITOR模式解决Shape排序问题

Robert C Martin 在他OCP(Open/Closed Principle,可以参考>)的教程里,以Shape作为例子,介绍如何运用OCP。 但是有一个问题没有给答案,只是说: “It is possible to solve this problem by using the ACYCLIC VISITOR pattern described in Chapter 35.

swimmer2000的专栏 1176

PnP 单目相机位姿估计(二):solvePnP利用二维码求解相机世界坐标

前言 原理简介 输入参数准备 1 objectPoints特征点世界坐标 2 imagePoints特征点在摄像头下的像素点坐标 3cameraMatrixdistCoeffs内参矩阵和畸变矩阵 相机世界坐标的求解 1求世界坐标中的点在相机坐标系下的坐标 2求相机在世界坐标中的坐标 3效果求解相机在世界坐标系下的坐标点 4求解代码1.前言  很多时候,当我们利用单目相机获取图像时,往往只能获取图像中

cocoaqin的博客 5万+

深入解析博世GTM DPLL:寄存器配置与状态监控实战指南

数字锁相环(DPLL)是一种用于精确跟踪和同步输入信号频率与相位的数字电路,其核心原理是通过数字环路滤波器处理相位误差,生成稳定的输出时钟。这项技术在嵌入式系统,尤其是对时序要求严苛的汽车电子领域具有极高的技术价值,是实现发动机控制单元(ECU)信号同步与高级驾驶辅助系统(ADAS)多传感器数据对齐的基石。其应用场景广泛覆盖了从工业控制到通信系统的各类需要高精度时钟管理的领域。本文将聚焦于博世GTM模块中的DPLL实现,详细剖析其寄存器配置逻辑与状态监控机制,帮助工程师掌握如何配置时间窗口、处理信号间隙以及

weixin_33725126的博客 432

(汇总篇)语义SLAM相关开源方案| 全球优秀作者与实验室 | SLAM学习资料整理

SLAM 与深度学习相结合的工作当前主要体现在两个方面,一方面是将语义信息参与到建图、位姿估计等环节中,另一方面是端到端地完成 SLAM。针对建图的工作一方面是利用几何信息进行稠密重建,另一方面很多工作利用语义信息达到了很好的语义重建效果,三维重建、SFM。动态 SLAM 也是一个很值得研究的话题,这里不太好分类,很多工作用到了语义信息或者用来三维重建,收集的方案相对较少。优化可能是 SLAM 中最难的一部分了吧 +_+ ,一般都是直接用现成的因子图、图优化方案,要创新可不容易。

熊猫小妖的AI世界 7869

敏捷软件开发 - 原则、模式与实践

起源 《敏捷软件开发 - 原则、模式与实践》是我接触到的第一本系统介绍软件设计的书籍,深刻影响了个人的软件开发习惯。它并不难懂,我一直推荐给身边的各个层次的程序员学习。 可对于一本接近500页的图书,很多人还是望而却步。一直都想写个关于这本书的速读,使更多的人了解它。但是最近又重新学习了一遍发现它之所以有价值不仅仅在于书中总结的原则和模式,更在于它提供的如何运用这些原则、模式的实践例子。忽略了大量...

feifeilb的博客 2377

Allegro如何设置走线自动删除重复走线操作指导

Allegro如何设置走线是自动删除重复走线操作指导在PCB布线的时候,点到点需要重复走一段线的时候,希望原来的线段自动被删除,Allegro设计的时候支持这个操作如下图,重复走中间的线段的时候,希望下方的走线自动删除具体操作如下This section is describe what the function allegro have ,helpfully could let user know more about allegroAllegro Design and Analysis includes

weixin_54787054的博客 4499

推荐:《敏捷软件开发、原则、模式与实践》电子版

 内容简介 在这本书中,享誉全球的软件开发专家和软件工程大师Robert C.Martin将向您展示如何解决软件开发人员、项目经理及软件项目领导们所面临的最棘手的问题。这本综合性、实用性的敏捷开发和极限编程方面的指南,是由敏捷开发的创始人之一所撰写的。   ·讲述在预算和实践要求下,软件开发人员和项目经理如何使用敏捷开发完成项目。   ·使用真实案例讲解如何用极限编程来设计、测试、重构和结

Scrum中文网-博客 1318

QT应用编程: 基于UDP协议设计的大文件传输软件

一、环境介绍 QT版本: 5.12.6 编译器: MinGW 32 传输协议: UDP 功能介绍:软件由客户端和服务器组成,客户端通过 UDP协议不断循环地向服务端发送文件,文件传输速率可以达到10MB/s以上,文件传输后支持自动删除,客户端上可以支持每分钟创建一个文件并以时间戳命名,每个生成的文件可以设置大小,默认大小为6GB; 服务端收到文件之后,将文件进行存储到本地,可以指定时间自动删除文件;服务端可以动态计算传输速率,并写入日志文件; 服务器可以支持同时接收多个客户端的文件上传。...

2803

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

推荐书籍系列(2):敏捷软件开发――原则、模式与实践

又名: Agile Software Development: Principles, Patterns, and Practices 译者: 邓辉作者: (美)Robert C·Martin 邓辉 孟岩 审 isbn: 7302071977页数: 500出版社: 清华大学出版社出版年: 2003-9-1 在这本书中,享誉全球的软件开发专家和软件工程大师Robert C.Martin将向您...

weixin_30267785的博客 145

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

敏捷软件开发 - 原则、模式与实践 —— 设计模式(十二)STATE模式

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。 本文对应原书第29章 STATE模式 STATE模式既具有switch/case语句的效率又具有解释迁移表的灵活性。 上图展示该模式的结构。Turnstile类拥有关于事件的公有方法以及关于动作的受保护方法。它持有一个指向TurnstileState接口的引用。当Turnstile的两个事件方法中的一个被调用时,它就把这个事件委托给Turn...

feifeilb的博客 563

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

敏捷软件开发 - 原则、模式与实践 —— 敏捷设计(八)包的耦合性原则

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。 本文对应原书第20章后半部分 包的耦合性原则 无环依赖原则(ADP - The Acyclic Dependencies Principle ) 在包的依赖关系图中不允许存在环。 解除依赖环的方法 使用依赖倒置原则。 创建一个新包,把共同依赖的类移动到新包里面。 稳定依赖原则(SDP - The Stable-Dependencies P...

feifeilb的博客 497

敏捷软件开发 - 原则、模式与实践 —— 敏捷设计(一)设计的臭味

设计的臭味 僵化性 僵化性是指难以对软件进行改动,即使是最简单的改动。如果单一的改动会导致有依赖关系的模块中的连锁改动,那么设计就是僵化的。必须要改动的模块越多,设计就越僵化。 脆弱性 脆弱性是指,在进行一个改动时,程序的许多地方就可能出现问题。常常是,出现新问题的地方与改动的地方并没有概念上的关联。 牢固性 牢固性是指,设计中包含了对其他系统有用的部分,但是要把这些部分从系统中分离出...

feifeilb的博客 486

敏捷软件开发 - 原则、模式与实践 —— 敏捷设计(七)包的内聚性原则

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。 本文对应原书第20章前半部分 包的内聚性原则 重用发布等价原则(REP - The Reuse/Release Equivalence Principle) 重用的粒度就是发布的粒度 REP指出,一个包的重用粒度可以和发布粒度一样大。我们所重用的任何东西都必须同时被发布和跟踪。简单的编写一个类,然后声称它是可重用的做法是不现实的。只有在建立一...

feifeilb的博客 456

敏捷软件开发 - 原则、模式与实践 —— 敏捷设计(六)接口隔离原则

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。 本文对应原书第12章。 接口隔离原则(ISP - The Interface Segregation Principle) 不应该强迫客户依赖于它们不用的方法。 这个原则用来处理“胖”接口所具有的缺点。如果类的接口不是内聚的,就表示该类具有“胖”的接口。换句话说,类的“胖”接口可以分解成多组方法。每一组方法都服务于一组不同的客户程序。这样,一...

feifeilb的博客 430

敏捷软件开发 - 原则、模式与实践 —— 设计模式(一)COMMAND模式和ACTIVE OBJECT模式

COMMAND模式 COMMAND模式是最简单、最优雅的模式之一。它的适用范围非常广泛。 图1 ACTIVE OBJECT模式 ACTIVE OBJECT模式是我最喜欢使用COMMAND模式的地方之一。这是实现多线程控制的一项古老技术。该模式有多种使用方式,为许多工业系统提供了一个简单的多任务核心。 图2 结论 COMMAND模式的简单性掩盖了它的多功能性。COMMAND模式可以应用于多种不同的美...

feifeilb的博客 427

敏捷软件开发 - 原则、模式与实践 —— 敏捷设计(二)单一责任原则

单一责任原则 (SRP - Single-Responsibility Principle) 就一个类而言,应该仅有一个引起它变化的原因。 在SRP中,我们把职责定义为‘变化的原因’。如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。 如果决定职责的粒度,要依赖于具体程序的变化方式。如果程序的变化会影响某一个细分职责,那就肯定要分开它们,否则会带来僵化性的臭味。但如果应用...

feifeilb的博客 393

敏捷软件开发 - 原则、模式与实践 —— 敏捷开发(二)

本文对应原书第3章 ~ 第6章。 计划 初始探索 在项目开始时,开发人员和客户会尽量确定出所有真正重要的用户用例。但,他们不会试图去确定所有的用户用例。注意用例的大小,过大或过小都不利于工作量的评估。 发布计划 根据开发速度,客户选择下面2-4个月需要完成的用户用例,并排列这些用例的优先级。发布计划可以调整。 迭代计划 根据开发速度,客户选择下面2周需要完成的用户用例,并排列这些用例的...

feifeilb的博客 387

敏捷软件开发 - 原则、模式与实践 —— 设计模式(九)ABSTRACT SERVER模式、ADAPTER模式和BRIDGE模式

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。 本文对应原书第25章 ABSTRACT SERVER模式 如上图在Switch和Light之间引入一个接口,这样就使得Switch能够控制任何实现了这个接口的东西。这立即就满足了DIP和OCP。这个就是ABSTRACT SERVER模式。 请注意接口的名字是从它的客户的角度起的。它被称为Switchable而不是ILight。我们在前面已经...

feifeilb的博客 370
上一篇: 敏捷软件开发 - 原则、模式与实践 —— 设计模式(十)PROXY模式和STAIRWAY TO HEAVEN模式
下一篇: 敏捷软件开发 - 原则、模式与实践 —— 设计模式(十二)STATE模式
feifeilb
博客等级 码龄22年 22粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值