Java geek


Related reading:

JAVA programming ideas (1) Increase extensibility through dependency injection (2) How to program for interface (3) Remove the ugly if, self-registration strategy mode elegant meet the open and close principle (4) JAVA programming ideas (Builder mode) classical paradigm and factory mode how to choose? Java Programming Ideas (5) Event Notification Decoupling Process (6) Event Notification Decoupling Process (7) Scenarios using Composition and Inheritance Java Basics (1) Simple and thorough understanding of inner classes and static inner classes Java basics (2) Memory optimization – Using Java references for caching JAVA foundation (3) ClassLoader implementation hot loading JAVA foundation (4) enumeration (enum) and constant definition, factory class use contrast JAVA foundation (5) functional interface – reuse, The sword of decoupling HikariPool source code (2) Design idea borrowed from JetCache source code (1) beginning JetCache source code (2) Top view people in the workplace (1) IT big factory survival rules


1. An overview of the

The relationship between design pattern, object-oriented principle and software quality attribute is shown as follows:

  1. Everything is done at the top to ultimately improve software quality attributes.

  2. Design principles are based on three principles of object orientation, which are the foundation of the upper layer.

  3. Encapsulating change is the foundation of interface oriented programming. If there is no change, there is no need to program interface, so encapsulating change is especially important.

  4. The design pattern follows the three principles of design and object orientation, and is also the reference of these principles in practice.

The above layers are related to each other and need to be comprehensively viewed to better practice and improve personal ability and software quality.

2. Design principles

Here will not do a detailed introduction to the design principles, this aspect of more information, you can refer to other materials together to see, here only to describe the basic concept and some experience.

2.2. Single responsibility

Refer to Java programming ideas (eight) how to achieve a single responsibility.

2.3. Open and close principle

Definition 2.3.1.

Open to extension, closed to modification. It can be understood as closed as possible to the modification of existing classes/modules, and new classes can be added to achieve the extension.

Example 2.3.2.

Tax calculation methods vary according to different scenarios, requiring dynamic acquisition algorithms, while allowing custom teams to extend the tax algorithm.

  1. The tax algorithm here is the point of change, so it needs to be abstracted.
  2. Custom teams need to be able to extend tax algorithms, so they need to support dynamic registration algorithms.

The final class structure diagram is as follows:

So when there is a new tax algorithm:

  1. Implement a new tax algorithm class
  2. Add a new tax type corresponding to the new algorithm class
  3. Register the new tax algorithm class with the TaxCalculatorRegistry class
  4. Obtain the corresponding tax algorithm class to calculate tax through TaxCalculatorRegistry

2.4. Richter substitution

Defined against 2.4.1.

The subclass object can replace the parent class object, and ensure that the original logical behavior and correctness of the program is not damaged.

This definition looks a lot like interface oriented programming, but in reality it is different. The Richter substitution principle satisfies interface oriented programming, but interface oriented programming does not necessarily satisfy The Richter substitution principle. The Richter substitution principle also contains constraints, emphasizing that the logical behavior of the program is unchanged and its correctness is not broken.

Example 2.4.2.

An interface subclass originally had poor performance and replaced the implementation of the new subclass. The interface remains the same, but a method did not throw exceptions. The new subclass threw runtime exceptions, which changed the original logical behavior and affected the processing logic of the calling side, strictly speaking, does not comply with the Richter substitution principle.

When code is called by a third party, pay special attention to the Richter’s substitution principle. If an exception is thrown suddenly without being told, it may seriously affect the processing logic of the calling side.

2.5. Interface isolation

Definition 2.5.1.

Interface design should be as simple as possible, do not let the interface implementation classes and callers, rely on interface functions that are not needed.

Example 2.5.2.

Ducks can quack, swim and fly, but not all ducks can swim and fly (e.g. plastic ducks), so interface isolation is needed to define interfaces for swimming and flying respectively.

If interface isolation is not implemented, the plastic duck will have to implement unnecessary interfaces, but there is no corresponding implementation, and will only throw an UnSupportException, which is unnecessary and meaningless.

2.5.4. Exception

In practice, all interfaces are defined together and an UnSupportException is thrown in an implementation that does not support subclasses. This violates the interface isolation principle, but sometimes it is unnecessary because interfaces are not self-defined but are defined by open source frameworks or industry standards. For example, jDBC-related interfaces may not support all methods when connecting to a company-implemented database, but they have to be standardized through the JDBC interface.

Therefore, this principle should be observed as far as possible, but there may be exceptions.

2.6. Dependency inversion

Definition 2.6.1.

High-level modules do not depend on low-level modules; they all depend on the same abstraction. Abstraction does not depend on concrete implementation details; concrete implementation details depend on abstraction.

Example 2.6.2.

Usually, the higher level will depend on the lower level, but there is no extensibility, will depend on the lower level implementation details, dependency inversion is usually found in some standard specifications, frameworks, etc., such as the JDBC interface specification:



The caller only needs to rely on the JDBC interface, and does not care about the specific implementation class of each vendor.

A similar example is the servlet specification, which allows developers to implement the interface of a servlet and be called in the corresponding Web container.

The dependency inversion principle reduces low-level coupling and applies to calls between frameworks, modules, and systems.

2.7. Demeter’s Rule

Definition 2.7.1.

The Law of Demeter, also known as The Least Knowledge Principle, states that a class should know as little as possible about other classes. It states that an object should know as little as possible about other objects and should only communicate with friends and not talk to strangers. Short for LOD

Example 2.7.2.

Design patterns such as Facade and Mediator are examples of the application of Demeter’s law.

3. Three principles of object orientation

3.1. Encapsulation changes

The benefits of encapsulating change are obvious, supporting design principles upward and securing multiple quality attributes of software downward. So how can you improve your ability to encapsulate change?

Usually, analysis can be done first in the design stage to preliminarily identify which functions may be the change points, draw a general class structure diagram and start coding. However, in fact, some details are not taken into account in the design stage, and not everyone can design first. Therefore, change points can also be identified in the reverse way, the process is as follows:

  1. Try not to write more than 20 lines of code per method, and when you do that, each method that can stand on its own can be a point of change. (Short methods can not only be used to identify changes, but also improve maintainability. For example, why should there be chapters for an article? If the book has a long content without chapter table of contents, you probably don’t want to read it, so writing short methods should always be carried out to the end)
  2. Check whether the implementation of each method is likely to change and can be extracted into a common method. If the answer is yes, it means you need to provide interfaces, categorization, use of design patterns such as factories and policies
  3. Further check whether the changepoint allows third parties to extend it. If the answer is yes, it means you may need to provide the ability to dynamically register the changepoint’s implementation classes, or to provide methods that allow the injection of concrete implementation classes through interfaces.
  4. Further check whether the change point needs to be a separate subpackage or a common package at the project level

Follow the above steps to continue to refactor it.

Matters needing attention:

  1. Each independent method does not necessarily need to be made public, but whether to make public should be decided according to actual needs. The most basic function of method independence is to improve maintainability.
  2. Consider the possibility of change. If it’s unlikely, don’t treat it as a point of change. Don’t create interfaces and design patterns just to make your code look big.

EventBus is a decoupled process of event notification mode. It is a decoupled process of event notification mode. It is a decoupled process of event notification mode

3.2. Interface oriented programming

How to interface programming JAVA basics (5) Functional interface – reuse, decoupled edge

3.3. Favor composition over inheritance

Reference: Java Programming Ideas (7) Scenarios using composition and inheritance

4. Summary of landing practice

1. The three principles of design pattern, design principle and object orientation are interrelated and need to be combined into practice.





2. The three principles of object orientation are the foundation, and the encapsulation of change points is the foundation of the foundation. It is necessary to give priority to improving this ability, writing small methods in practice and identifying possible change points can help improve this ability.





3. After identifying the change point, how to divide the responsibilities of the class, and whether to separate and classify and subcontract independently; Whether or not to use interface oriented programming depends on which design pattern you can apply.





4. Optimization in the continuous reconstruction, do not have to set a design pattern, interface oriented programming, as long as it can reasonably split method, thereby dividing the responsibilities of the class, and have the relevant knowledge background, the reconstruction is fast.


end.


<– Read the mark, left like!