提交 233b4e80 编写于 作者: W wizardforcel

2020-06-11 22:52:32

上级 7fbc8e08
......@@ -25,9 +25,9 @@ Summary
**策略模式**使客户端代码可以从一系列相关但不同的算法中进行选择,并提供了一种简单的方法来根据客户端上下文在运行时选择任何算法。
#### 由开/关原驱动
#### 由开/关原驱动
该模式基于**打开/关闭原理**。 我们不需要修改上下文(已关闭以进行修改),但是可以选择并添加任何实现(可扩展用于开放)。
该模式基于**开闭原则**。 我们不需要修改上下文(已关闭以进行修改),但是可以选择并添加任何实现(可扩展用于开放)。
例如,在`Collections.sort()`中 - 我们无需更改排序方法即可获得不同的排序结果。 我们可以在运行时提供不同的比较器。
......
......@@ -24,7 +24,7 @@ How to use visitors in application code
## 访问者模式介绍
根据维基百科所述, [**访问者设计模式**](https://en.wikipedia.org/wiki/Visitor_pattern "visitor pattern")是一种将算法与操作对象的结构分离的方法。 这种分离的实际结果是能够在不修改那些对象结构的情况下向现有对象结构添加新操作。 这是遵循**打开/关闭原则**[**SOLID 设计原则**](//howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/ "5 class design principles [S.O.L.I.D.] in java") 之一)的一种方法。
根据维基百科所述, [**访问者设计模式**](https://en.wikipedia.org/wiki/Visitor_pattern "visitor pattern")是一种将算法与操作对象的结构分离的方法。 这种分离的实际结果是能够在不修改那些对象结构的情况下向现有对象结构添加新操作。 这是遵循**闭原则**[**SOLID 设计原则**](//howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/ "5 class design principles [S.O.L.I.D.] in java") 之一)的一种方法。
上面的设计灵活性允许将方法添加到任何对象层次结构,而无需修改为层次结构编写的代码。 而是使用[**双调度**](https://en.wikipedia.org/wiki/Double_dispatch "double dispatch")机制来实现此功能。 双调度是一种特殊的机制,可以根据调用中涉及的两个对象的运行时类型,将函数调用分派给不同的具体函数。
......
......@@ -52,7 +52,7 @@
如果您在此处停止并且不再修改系统,则它将起作用。 但是,假设几天后,**您被告知为两种报告应用不同的背景色**。 现在,您只有一种方法可以在两个类中定义方法`colorBackground()`,并进行适当的调用。 将来系统中有更多报告时,问题将变得更加严重。
上面的解决方案明显违反了 [**SMART 类别设计**](//howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/ "SMART principles for class design")中提到的**打开/关闭原则**
上面的解决方案明显违反了 [**SMART 类别设计**](//howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/ "SMART principles for class design")中提到的**闭原则**
## 使用装饰器设计模式的建议解决方案
......@@ -70,7 +70,7 @@
## 源代码列表
让我们看一看上课的源代码,以了解其实际外观。
让我们看一看的源代码,以了解其实际外观。
**`Report.java`**
......
# Java 中的 SOLID 原理[含示例]
# Java 中的 SOLID 原则(含示例)
> 原文: [https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/](https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/)
......@@ -6,7 +6,7 @@
另一方面,精心设计和编写的类集可以极大地加快编码过程,同时减少比较中的错误数量。
在本教程中,我们将通过示例讨论 Java 中的 **SOLID 原则,这是 5 种最推荐的设计原则,在编写类时应牢记。 它们还构成设计应用类时要遵循的 [**最佳做法**](//howtodoinjava.com/category/best-practices/ "java best practices") 。**
在本教程中,我们将通过示例讨论 Java 中的 **SOLID 原则**,这是 5 种最推荐的设计原则,在编写类时应牢记。 它们还构成设计应用类时要遵循的[**最佳做法**](//howtodoinjava.com/category/best-practices/ "java best practices")
```java
Table Of Contents
......@@ -20,7 +20,7 @@ Table Of Contents
![5 java class design principles](img/12fd0c2b43b551f8ce16188cd4dceca1.png)
5 java class design principles
5 个 Java 类设计原则
......@@ -30,7 +30,7 @@ Table Of Contents
原则的名称说明了一切:
> “一堂课应该只有一个责任”
> “一个类应该只有一个责任”
换句话说,我们应该仅出于一个目的编写,更改和维护类。 如果是模型类,则它应严格只代表一个参与者/实体。 这将使我们能够灵活地在将来进行更改,而不必担心更改对另一个实体的影响。
......@@ -38,11 +38,11 @@ Table Of Contents
#### 1.1 单一责任原则示例
在所有流行的 Java 库中,我们都可以找到很多遵循单一职责原则的类。 例如,在 log4j 中,我们具有使用日志记录方法的不同类,不同的类是日志记录级别,依此类推。
在所有流行的 Java 库中,我们都可以找到很多遵循单一责任原则的类。 例如,在 log4j 中,我们具有使用日志记录方法的不同类,不同的类是日志记录级别,依此类推。
在我们的应用级代码中,我们定义了模型类来表示实时实体,例如人,雇员,帐户等。这些类中的大多数是 SRP 原的示例,因为当我们需要更改人的状态时,才需要修改 一个人的类。 等等。
在我们的应用级代码中,我们定义了模型类来表示实时实体,例如人,雇员,帐户等。这些类中的大多数是 SRP 原的示例,因为当我们需要更改人的状态时,才需要修改 一个人的类。 等等。
在给定的示例中,我们有两个类`Person``Account`。 两者都负有存储其特定信息的单一责任。 如果要更改 Person 的状态,则无需修改类`Account`,反之亦然。
在给定的示例中,我们有两个类`Person``Account`。 两者都负有存储其特定信息的单一责任。 如果要更改`Person`的状态,则无需修改类`Account`,反之亦然。
```java
public class Person
......@@ -70,21 +70,21 @@ public class Account
## 2.开闭原则
这是设计应用时应牢记的第二个重要规则。 **开闭原**指出:
这是设计应用时应牢记的第二个重要规则。 **开闭原**指出:
> “软件组件应打开以进行扩展,但应关闭以进行修改
> “软件组件应为扩展开放,但应为修改封闭
这是什么意思?? 这意味着我们的类应该这样设计:每当开发人员想要改变应用中特定条件下的控制流时,他们都需要扩展我们的类并覆盖某些功能,仅此而已。
如果其他开发人员由于类的约束而无法设计所需的行为,则应重新考虑更改类。 在这里我并不是说任何人都可以改变我们班级的整体逻辑,但是他/她应该能够以软件允许的无害方式覆盖软件提供的选项。
如果其他开发人员由于类的约束而无法设计所需的行为,则应重新考虑更改类。 在这里我并不是说任何人都可以改变我们的整体逻辑,但是他/她应该能够以软件允许的无害方式覆盖软件提供的选项。
#### 2.1 开闭原示例
#### 2.1 开闭原示例
如果我们研究诸如 struts 或 spring 之类的任何良好框架,我们将看到我们无法更改其核心逻辑和请求处理,但仅通过扩展某些类并将其插入配置文件中即可修改所需的应用流。
例如,spring 框架具有类`DispatcherServlet`。 此类充当基于 String 的 Web 应用的**前端控制器**。 要使用此类,我们不需要修改此类。 我们所需要做的就是传递初始化参数,然后我们可以按需要扩展其功能。
请注意,除了在应用启动期间传递初始化参数之外,我们还可以重写方法,以通过扩展类来修改目标类的行为。 例如,struts Action 类被扩展以覆盖请求处理逻辑。
请注意,除了在应用启动期间传递初始化参数之外,我们还可以重写方法,以通过扩展类来修改目标类的行为。 例如,struts `Action`类被扩展以覆盖请求处理逻辑。
```java
public class HelloWorldAction extends Action
......@@ -104,15 +104,15 @@ public class HelloWorldAction extends Action
```
## 3\. Liskov 的替代原则
## 3\. 里氏替代原则
该原理是先前讨论的打开 - 闭合原理的变体。 它说:
该原则是先前讨论的打开 - 闭合原则的变体。 它说:
> “派生类型必须完全可以替代其基本类型”
这意味着通过扩展我们的类而创建的同级开发人员应该能够适合应用而不会失败。 这要求子类的对象的行为与父类的对象相同。 这通常在我们进行运行时类型识别然后将其转换为适当的引用类型的地方看到。
#### 3.1 Liskov 替代原理示例
#### 3.1 里氏替代原则示例
LSP 的一个示例可以是 Spring 框架中的[自定义属性编辑器](https://howtodoinjava.com/spring-boot/custom-property-editor-example/)。 Spring 提供了属性编辑器以与对象本身不同的方式表示属性,例如,从 HTTP 请求参数解析人类可读的输入或在视图层中显示纯 Java 对象的人类可读的值,例如 `Currency``URL`
......@@ -148,11 +148,11 @@ public class IsbnEditor extends PropertyEditorSupport {
```
## 4.接口隔离原
## 4.接口隔离原
这是我最喜欢的原则。 它适用于接口,因为单一职责原则适用于类。 ISP 说:
这是我最喜欢的原则。 它适用于接口,因为单一责任原则适用于类。 ISP 说:
> “不应强迫客户实现不必要的不​​必要的方法”
> “不应强迫客户实现不必要的方法”
举个例子。 开发人员 Alex 创建了一个接口`Reportable`并添加了两种方法`generateExcel()``generatedPdf()`。 现在,客户“ A”希望使用此界面,但他打算仅使用 PDF 格式的报告,而不使用 excel。 他将能够轻松使用该功能吗?
......@@ -160,18 +160,18 @@ public class IsbnEditor extends PropertyEditorSupport {
那么解决方案是什么? 解决方案是通过破坏现有接口来创建两个接口。 它们应该像`PdfReportable``ExcelReportable`。 这将为用户提供灵活性,使其仅使用必需的功能。
#### 4.1 接口隔离原示例
#### 4.1 接口隔离原示例
查找 IPS 示例的最佳地方是 Java AWT 事件处理器,用于处理从键盘和鼠标触发的 GUI 事件。 对于每种事件,它都有不同的监听器类。 我们只需要编写希望处理的事件处理器即可。 没有什么是强制性的。
一些听众是:
一些监听器是:
* FocusListener
* 监听器
* MouseMotionListener
* MouseWheelListener
* 文字监听器
* WindowFocusListener
* `FocusListener`
* `KeyListener`
* `MouseMotionListener`
* `MouseWheelListener`
* `TextListener`
* `WindowFocusListener`
任何时候,我们希望处理任何事件,只需找出相应的监听器并实现它即可。
......@@ -193,19 +193,19 @@ public class MouseMotionListenerImpl implements MouseMotionListener
## 5.依赖倒置原则
我们大多数人已经熟悉原则名称中使用的词语。 DI 原说:
我们大多数人已经熟悉原则名称中使用的词语。 DI 原说:
> “取决于抽象而不是具体”
> “依赖抽象而不是具体”
换一种说法。 我们应该以这样一种方式设计我们的软件,即可以使用抽象层将各个模块彼此绑定在一起,从而将各个模块彼此分离。
#### 5.1 依赖倒置原示例
#### 5.1 依赖倒置原示例
Spring 框架中`bean configuration`原理的经典用法。
Spring 框架中 Bean 配置原则的经典用法。
在 spring 框架中,所有模块都作为单独的组件提供,可以通过简单地将依赖注入到其他模块中来一起工作。 此依赖关系在 XML 文件中从外部进行管理。
这些独立的组件在边界上封闭得非常好,以至于我们可以轻松地在 Spring 之外的其他软件模块中使用它们。 这已经通过依赖倒置和开放封闭原则来实现。 所有模块仅公开抽象,这对于扩展功能或另一个模块中的插件很有用。
这些独立的组件在边界上封闭得非常好,以至于我们可以轻松地在 Spring 之外的其他软件模块中使用它们。 这已经通过依赖倒置和开闭原则来实现。 所有模块仅公开抽象,这对于扩展功能或另一个模块中的插件很有用。
这些是**五类设计原则**,也称为 **SOLID 原则**,这是设计应用类别时应遵循的最佳实践。
......
......@@ -2,25 +2,25 @@
> 原文: [https://howtodoinjava.com/design-patterns/open-closed-principle/](https://howtodoinjava.com/design-patterns/open-closed-principle/)
**打开/关闭原理**(OCP)指出,模块应该可以扩展,但可以关闭以进行修改。 它是著名的 5 条[实体原则](https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/)和非常重要的*面向对象设计原则*之一。
**开闭原则**(OCP)指出,模块应该可以扩展,但可以关闭以进行修改。 它是著名的 5 条[实体原则](https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/)和非常重要的*面向对象设计原则*之一。
## 1.开放封闭原则的定义
## 1.开闭原则的定义
有两种流行的定义来描述这一原
有两种流行的定义来描述这一原
#### 1.1 迈耶的定义
伯特兰·梅耶(Bertrand Mayer)在其 1988 年的著作*面向对象的软件构造(Prentice Hall)*中,定义了开放/封闭原则(OCP)如下:
伯特兰·梅耶(Bertrand Mayer)在其 1988 年的著作面向对象的软件构造(Prentice Hall)中,定义了开闭原则(OCP)如下:
> 软件实体应为扩展而开放,但应为修改而封闭。
#### 1.2 迈耶的定义
Robert C. Martin 在他的书《 *敏捷软件开发:原理,模式和实践》(Prentice Hall,2003 年)*中定义了 OCP,如下所示:
Robert C. Martin 在他的书《敏捷软件开发:原则,模式和实践》(Prentice Hall,2003 年)中定义了 OCP,如下所示:
**打开扩展** – 这意味着可以扩展模块的行为。 随着应用需求的变化,我们能够通过满足这些变化的新行为来扩展模块。 换句话说,我们能够更改模块的功能。
**开放扩展** – 这意味着可以扩展模块的行为。 随着应用需求的变化,我们能够通过满足这些变化的新行为来扩展模块。 换句话说,我们能够更改模块的功能。
**已关闭,可修改** – 扩展模块的行为不会导致模块的源代码或二进制代码更改。 模块的二进制可执行版本,无论是在可链接库,DLL 还是 Java .jar 中,都保持不变。
**封闭修改** – 扩展模块的行为不会导致模块的源代码或二进制代码更改。 模块的二进制可执行版本,无论是在可链接库,DLL 还是 Java .jar 中,都保持不变。
## 2.讨论
......@@ -28,37 +28,37 @@ Robert C. Martin 在他的书《 *敏捷软件开发:原理,模式和实践
#### 2.1 例外情况
请注意,在**的情况下,几乎绝对需要修改代码**并且无法避免。
请注意,在少数情况下,绝对有必要修改代码,并且无法避免。
* One such example is existing defects in the module. In case of fixing the defects, module code changes are allowed and their respective testcases as well.
* 这样的例子之一就是模块中存在的缺陷。 在修复缺陷的情况下,允许更改模块代码及其相应的测试用例。
我们可以使用 [TDD](https://en.wikipedia.org/wiki/Test-driven_development) 方法来解决代码中的这些问题。 修正错误后,您必须确保没有其他测试会因副作用而失败。
* Another permissive exception is that any change to existing code is allowed as long as it does not also require a change to any client of that code. This allows the upgrade of the module versions with new language features. For example, [Spring 5](https://howtodoinjava.com/spring-5-tutorial/) supports and uses [Java8 lambda](https://howtodoinjava.com/java-8-tutorial/) syntax but to use it, we do not require to change our client application code.
* 另一个允许的例外情况是,允许对现有代码进行任何更改,只要它也不需要更改该代码的任何客户端即可。 这允许使用新的语言功能升级模块版本。 例如,[Spring 5](https://howtodoinjava.com/spring-5-tutorial/) 支持并使用 [Java8 lambda](https://howtodoinjava.com/java-8-tutorial/) 语法,但要使用它,我们不需要更改我们的客户端应用代码。
一个模块,其中的类是松散耦合的,在不强迫其他类更改的情况下更改了类,这就是鼓励松散耦合的原因。 如果您允许对现有代码进行修改而不会强制对客户端进行进一步更改,则保持松散的耦合将限制 OCP 的影响。
#### 2.2 如何设计开放封闭原则
#### 2.2 如何设计开闭原则
为了实现模块的扩展,我们可以采用两种(通常使用的)机制中的任何一种。
###### 2.2.1 实现继承
实现继承使用 [**抽象类和方法**](https://howtodoinjava.com/java/basics/abstract-keyword/) 。 您可以将扩展点定义为抽象方法。
实现继承使用[**抽象类和方法**](https://howtodoinjava.com/java/basics/abstract-keyword/)。 您可以将扩展点定义为抽象方法。
该抽象类可以由几个具有大多数常见场景的预定义实现的类扩展。 对于特定于客户的场景,开发人员必须扩展抽象类并提供特定的实现逻辑。 这将有助于保留 OCP。
[**模板方法模式**](https://howtodoinjava.com/design-patterns/behavioral/template-method-pattern/) 非常适合这些用例。 在这种模式下,由于可以委托抽象方法,因此可以自定义一般步骤。 实际上,基类将流程的各个步骤委托给子类。
[**模板方法模式**](https://howtodoinjava.com/design-patterns/behavioral/template-method-pattern/)非常适合这些用例。 在这种模式下,由于可以委托抽象方法,因此可以自定义一般步骤。 实际上,基类将流程的各个步骤委托给子类。
###### 2.2.2 接口继承
[接口](https://howtodoinjava.com/oops/exploring-interfaces-and-abstract-classes-in-java/)继承中,客户端对类的依赖关系被替换为接口。 与抽象方法相比,这实际上是首选方法。 这呼应了这样的建议,即首选组合而不是[继承](https://howtodoinjava.com/oops/java-inheritance/),并保持继承层次结构较浅,并且子分类层很少。
> 设计继承或禁止继承。 – 有效的 Java(Addison-Wesley,2008 年),约书亚·布洛赫(Joshua Bloch)
> 设计继承或禁止继承。 – Effective Java(Addison-Wesley,2008 年),约书亚·布洛赫(Joshua Bloch)
## 3.开闭原示例
## 3.开闭原示例
如果要查看**开放式封闭原理的真实示例**,只需看一下 **Spring 框架**即可。 Spring 的设计和实现非常精美,因此您可以扩展其功能的任何部分,并立即将自定义实现注入。 它经过了很好的时间测试,并且像今天一样完美无缺。
如果要查看**开闭原则的真实示例**,只需看一下 **Spring 框架**即可。 Spring 的设计和实现非常精美,因此您可以扩展其功能的任何部分,并立即将自定义实现注入。 它经过了很好的时间测试,并且像今天一样完美无缺。
#### 3.1 没有 OCP 的计算器程序
......@@ -137,7 +137,7 @@ public class SimpleCalculator implements ICalculator
#### 3.2 符合 OCP 的代码
请记住,抽象功能是应用中的变化。 在此计算器程序中,calculate 方法中的代码将随每个传入的新操作支持请求而变化。 因此,我们需要在此方法中添加抽象。
请记住,抽象功能是应用中的变化。 在此计算器程序中,`calculate`方法中的代码将随每个传入的新操作支持请求而变化。 因此,我们需要在此方法中添加抽象。
解决方案是委派在操作本身内部提供计算逻辑的责任。 每个操作必须具有自己的逻辑才能获取结果和操作数。 现在查看修改后的代码。
......@@ -241,7 +241,7 @@ public class Multiplication implements IOperation
## 4\. 结论
**打开/关闭原则**是类和接口的总体设计以及开发人员如何构建允许随时间变化的代码的指南。
**闭原则**是类和接口的总体设计以及开发人员如何构建允许随时间变化的代码的指南。
现在,当大多数组织都在采用[敏捷实践](https://en.wikipedia.org/wiki/Agile_software_development)时,每次经过 sprint 时,新的需求都是不可避免的,应该被接受。 如果您生成的代码不是为了进行更改而构建的,则更改将很困难,耗时,容易出错且成本很高。
......@@ -253,4 +253,4 @@ public class Multiplication implements IOperation
阅读更多:
[Wikipedia](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)
\ No newline at end of file
[维基百科](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)
\ No newline at end of file
......@@ -2,11 +2,11 @@
> 原文: [https://howtodoinjava.com/design-patterns/single-responsibility-principle/](https://howtodoinjava.com/design-patterns/single-responsibility-principle/)
**单一职责原则**(SRP)指出,软件组件(通常为类)必须仅具有一个职责。 班级负有全部责任这一事实意味着,班级只负责一件具体的事情,因此,我们可以得出结论,班级只有一个改变的理由。 它是 5 个著名的 [SOLID 原理](https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/)之一。
**单一责任原则**(SRP)指出,软件组件(通常为类)必须仅具有一个职责。 类负有全部责任这一事实意味着,类只负责一件具体的事情,因此,我们可以得出结论,类只有一个改变的理由。 它是 5 个著名的 [SOLID 原则](https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/)之一。
> 一个班级只有一个改变的理由。
> 一个只有一个改变的理由。
还有另一种看待这一原的方法。 如果在查看一个类时,我们发现相互排斥且彼此不相关的方法,则它们是必须分解为较小类的不同职责。 请记住,较小的类总是更好。
还有另一种看待这一原的方法。 如果在查看一个类时,我们发现相互排斥且彼此不相关的方法,则它们是必须分解为较小类的不同职责。 请记住,较小的类总是更好。
## 1.动机
......@@ -14,13 +14,13 @@
## 2.单一责任原则示例
要了解**单责任原则的真实示例**,我们可以看一下 JDK 代码和其他流行的库,例如 Log4J,Spring 框架等。Log4J 代码具有使用日志记录方法的不同类,不同的类是日志记录级别等等。 上。 在 Spring 框架中,类实际上很小,通常只执行一两个相关操作。
要了解**单责任原则的真实示例**,我们可以看一下 JDK 代码和其他流行的库,例如 Log4J,Spring 框架等。Log4J 代码具有使用日志记录方法的不同类,不同的类是日志记录级别等等。 在 Spring 框架中,类实际上很小,通常只执行一两个相关操作。
让我们再举一个自己的例子,以更好地理解什么是单一责任原则。
#### 2.1 问题
为了理解 SRP 原,我们假设我们正在开发涉及与员工一起工作的应用。 我们有一个接口`IEmployeeStore`,它的实现`EmployeeStore`具有以下方法。
为了理解 SRP 原,我们假设我们正在开发涉及与员工一起工作的应用。 我们有一个接口`IEmployeeStore`,它的实现`EmployeeStore`具有以下方法。
```java
public interface IEmployeeStore
......@@ -56,9 +56,9 @@ public class EmployeeStore implements IEmployeeStore
在任何普通应用上,上述类似乎都不错。 使用`EmployeeStore`,可以获取/添加员工并向他们发送电子邮件。
现在假设产品发布后,我们要求电子邮件内容可以是两种类型,即 HTML 和文本。 上课支持仅文本内容。 你会做什么?
现在假设产品发布后,我们要求电子邮件内容可以是两种类型,即 HTML 和文本。 该类支持仅文本内容。 你会做什么?
解决此问题的一种方法是创建另一种方法 **sendHtmlEmail()**,但是当我们被要求支持为两种内容类型发送电子邮件的不同协议时会发生什么。 整体类看起来非常丑陋,难以阅读和维护。
解决此问题的一种方法是创建另一种方法`sendHtmlEmail()`,但是当我们被要求支持为两种内容类型发送电子邮件的不同协议时会发生什么。 整体类看起来非常丑陋,难以阅读和维护。
而且总是有机会在修改期间,某些开发人员可以更改用于共享员工方法的获取/添加员工方法的逻辑。
......@@ -141,17 +141,17 @@ public class EmailContent implements IEmailContent
当类仅做“一件事情”时,其接口通常具有较少数量的方法(和成员变量),这些方法很容易解释。 它使代码更易于阅读和理解。
当需要更改应用行为时,与班级职责相关的更改是相当隔离的。 它减少了破坏软件其他无关区域的机会。 它使代码更易于维护。
当需要更改应用行为时,与职责相关的更改是相当隔离的。 它减少了破坏软件其他无关区域的机会。 它使代码更易于维护。
#### 3.2 改善的可用性
如果一个班级有多个职责,并且为了某个职责而需要在应用的其他部分中使用它,则可能不利地暴露其他职责,而这是不希望的。 它可能导致应用中不良行为,例如,安全和数据隐私问题。
如果一个有多个职责,并且为了某个职责而需要在应用的其他部分中使用它,则可能不利地暴露其他职责,而这是不希望的。 它可能导致应用中不良行为,例如,安全和数据隐私问题。
如果该类严格遵循 **SRP 原**,则不会暴露出不必要的功能,这将使该类更加可用,而不必担心会产生不利影响。
如果该类严格遵循 **SRP 原**,则不会暴露出不必要的功能,这将使该类更加可用,而不必担心会产生不利影响。
## 4\. 结论
**单责任原则设计模式**对代码的适应性具有巨大的积极影响。 与不遵循该原的等效代码相比,符合 SRP 的代码导致产生了更多的类,这些类更小且指向范围更广。
**单责任原则设计模式**对代码的适应性具有巨大的积极影响。 与不遵循该原的等效代码相比,符合 SRP 的代码导致产生了更多的类,这些类更小且指向范围更广。
SRP 的实现主要是通过抽象接口后的代码并将不相关功能的职责委托给运行时恰好在接口后的实现来实现的。
......
......@@ -2,7 +2,7 @@
> 原文: [https://howtodoinjava.com/best-practices/first-principles-for-good-tests/](https://howtodoinjava.com/best-practices/first-principles-for-good-tests/)
在解决现实问题的任何应用中,单元测试中都存在问题 – 是最不希望的事情。 [好的书面测试](//howtodoinjava.com/best-practices/unit-testing-best-practices-junit-reference-guide/)是资产,而不好的书面测试是您应用的负担。 在本教程中,我们将学习**单元测试 FIRST 原**,它可以使您的测试脱颖而出,并确保其收益超过成本。
在解决现实问题的任何应用中,单元测试中都存在问题 – 是最不希望的事情。 [好的书面测试](//howtodoinjava.com/best-practices/unit-testing-best-practices-junit-reference-guide/)是资产,而不好的书面测试是您应用的负担。 在本教程中,我们将学习**单元测试 FIRST 原**,它可以使您的测试脱颖而出,并确保其收益超过成本。
## 良好单元测试的首要原则
......
......@@ -80,7 +80,7 @@ mvn eclipse:eclipse -Dwtpversion=2.0
```
## 编写第一堂课
## 编写第一个类
这很重要,因为您将在此处编写实际的应用逻辑。 Struts 2 操作通常扩展 **ActionSupport** 类,该类提供了一些方法来覆盖和更改应用流,并在两者之间注入业务逻辑。
......
......@@ -82,7 +82,7 @@ public class DemoCustomInterceptor implements Interceptor
```
## 4)申请任何动作
## 4)申请任何动作
我在一个这样的 TestAction 类中应用了上面的拦截器。
......
......@@ -110,7 +110,7 @@ Wrapping data and methods within classes in combination with implementation hidi
另外,如果我说的不同:是否可以将许多*分组在一起并用一个名词描述的类? 如果是这样,请以该名词的名称创建一个抽象类,并从其继承这些类。 例如,`Cat`和`Dog`都可以从抽象类`Animal`继承,并且此抽象基类将实现方法`void breathe()`,所有动物都将以完全相同的方式执行该方法。*
什么样的动词可以应用于我的班级,通常也可以应用于其他动词? 为每个动词创建一个接口。 例如,所有动物都可以喂食,因此我将创建一个名为`IFeedable`的接口,并让`Animal`实现该接口。 尽管`Dog`和`Horse`足以实现`ILikeable`,但有些还不够。
什么样的动词可以应用于我的,通常也可以应用于其他动词? 为每个动词创建一个接口。 例如,所有动物都可以喂食,因此我将创建一个名为`IFeedable`的接口,并让`Animal`实现该接口。 尽管`Dog`和`Horse`足以实现`ILikeable`,但有些还不够。
正如某人所说:主要区别在于您想要实现的地方。 通过创建接口,可以将实现移动到实现接口的任何类。 通过创建一个抽象类,您可以在一个中央位置共享所有派生类的实现,并且避免了很多不好的事情,例如代码重复。
......
......@@ -43,7 +43,7 @@ Deep copy and shallow copy?
Java 中的同步是使用 synced 关键字实现的。 您可以在类中的已定义方法或块上使用 synced 关键字。 关键字不能与类定义中的变量或属性一起使用。
***对象级别锁定*** 是一种机制,当您要同步非静态方法或非静态代码块,以便仅一个线程将能够在给定实例的代码上执行代码块时, 班级。 应该始终这样做以确保实例级数据线程安全。
***对象级别锁定*** 是一种机制,当您要同步非静态方法或非静态代码块,以便仅一个线程将能够在给定实例的代码上执行代码块时, 。 应该始终这样做以确保实例级数据线程安全。
***类级别锁定*** 可防止多个线程在运行时进入所有可用实例中的任何同步块。 这意味着,如果在运行时有 100 个 DemoClass 实例,则一次只能在一个实例中的任何一个线程上执行 demoMethod(),而所有其他实例将被其他线程锁定。 为了确保静态数据线程的安全,应该始终这样做。
......@@ -100,7 +100,7 @@ Java 类,字段,构造函数和方法可以具有四种不同的访问修饰
***私有***
如果将方法或变量标记为私有,则只有同一类内的代码才能访问该变量或调用该方法。 子类中的代码无法访问变量或方法,也不能从任何外部类中进行代码。
如果将一个班级标记为私有,则没有外部班级可以访问该班级。 不过,对于班级来说,这实际上没有多大意义。 因此,访问修饰符 private 主要用于字段,构造函数和方法。
如果将一个类标记为私有,则没有外部类可以访问该类。 不过,对于类来说,这实际上没有多大意义。 因此,访问修饰符 private 主要用于字段,构造函数和方法。
***默认***
......@@ -152,7 +152,7 @@ protected acces 修饰符的作用与默认访问权限相同,除了子类还
Java 提供了自动序列化,该序列化要求通过实现 java.io.Serializable 接口来标记对象。 实现该接口会将类标记为“可以序列化”,然后 Java 将在内部处理序列化。 在可序列化接口上没有定义任何序列化方法,但是可序列化类可以选择定义具有某些特殊名称和签名的方法,如果定义了这些特殊名称和签名,这些方法将在序列化/反序列化过程中被调用。
对象序列化后,其类中的更改会破坏反序列化过程。 要确定您的班级中将来的变化,这些变化将是兼容的,而其他变化将被证明是不兼容的,请在此处 阅读完整的 [**指南。 简而言之,我在这里列出:**](//howtodoinjava.com/java/serialization/a-mini-guide-for-implementing-serializable-interface-in-java/ "A mini guide for implementing serializable interface in java")
对象序列化后,其类中的更改会破坏反序列化过程。 要确定您的中将来的变化,这些变化将是兼容的,而其他变化将被证明是不兼容的,请在此处 阅读完整的 [**指南。 简而言之,我在这里列出:**](//howtodoinjava.com/java/serialization/a-mini-guide-for-implementing-serializable-interface-in-java/ "A mini guide for implementing serializable interface in java")
**不兼容的更改**
......
......@@ -23,7 +23,7 @@ Table of Contents
## 1.什么时候使用工厂模式?
工厂模式引入了**类之间的松散耦合**,这是在设计应用架构时应考虑并应用的最重要的原。 通过针对抽象实体(而不是具体的实现)进行编程,可以在应用架构中引入松耦合。 这不仅使我们的架构更加灵活,而且不那么脆弱。
工厂模式引入了**类之间的松散耦合**,这是在设计应用架构时应考虑并应用的最重要的原。 通过针对抽象实体(而不是具体的实现)进行编程,可以在应用架构中引入松耦合。 这不仅使我们的架构更加灵活,而且不那么脆弱。
一张图片胜过千言万语。 让我们看看工厂实现的样子。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册