“The only constant in the world is constant change,” the product manager told me, pointing to the newly changed requirements. What am I going to do as a helpless programmer, arguing all the time that the demand for the product is there, where’s your code? So when we write code, we need to be prepared for unexpected changes in requirements. Fortunately, there are six great design principles and 23 design patterns that can help us “encapsulate” change and implement changing requirements with smart code.

The six principles

  • The Single Responsibility Principle
  • The Open Closed Principle
  • The Liskov Substitution Principle
  • The Law of Demeter
  • Interface Segregation Principle: indicates the Interface isolation Principle
  • The Dependence Inversion Principle

Take all distinct initials: SOLID (SOLID, stable)

Single responsibility principle

The responsibilities of a class should be single, with a method doing only one thing. Responsibilities are clearly delineated, each change to the smallest unit of methods or classes. Try to make sure that there is only one reason for change.

How the responsibilities of a class or a function are divided depends on personal experience and the specific business logic. But it also has some basic guidelines:

  1. Two completely different functions should not be in one class
  2. A class should be a set of highly correlated functions, data encapsulation
  3. You should always look at your code, break down classes for specific businesses and functions, and optimize your code

Richter’s substitution principle

All references to the base class must be able to be replaced directly by its subclasses. This principle is closely related to the object-oriented inheritance nature

  1. A child class must implement all methods of the parent class (inheritance property, the child class owns all methods of the parent class)
  2. Subclasses can have their own personalities (rewrite)
  3. When overwriting or implementing methods of the parent class, the arguments can be enlarged (e.g., HashMap for the parent class, Map for the subclass); The output can be narrowed (e.g., parent class return Map, subclass return HashMap)

Dependency inversion

  1. High-level modules should not depend on low-level modules; both should depend on their abstractions. The indivisible atomic logic is the low-level pattern, and the assembly of the atomic logic is the high-level module.

  2. Abstraction should not depend on details in Java, abstraction -> interface or abstract class; Details -> Implementation class

  3. Details should depend on abstractions

Interface oriented programming is one of the essence of object-oriented design. It can reduce the coupling between classes, improve the stability of the system, and reduce the risk caused by parallel development.

  • Intermodule dependencies occur through abstractions (interfaces), and there are no direct dependencies between implementation classes
  • An interface or abstract class does not depend on an implementation class
  • Implementation classes depend on interfaces or abstract classes

Interface isolation Rule

A client should not rely on interfaces it does not need. (The interface here is divided into instance interface, i.e., class interface, so the interface here in Java means class and interface) To establish a single interface, do not establish a bloated interface, and the difference with SRP: SRP for responsibilities, from the business logic division; Isps are required to interface as few methods as possible.

  1. Keep the interface small
  2. High cohesion of interfaces: Improve the processing capability of interfaces, classes and modules, reduce external interaction, and require to publish as few public methods as possible in interfaces. Reducing external commitments is also beneficial to reducing costs
  3. Custom service, for different users to provide a good service, only provide the visitor needs the method. For example, users with different permissions are assigned different operation interfaces.
  4. The smaller the interface granularity, the more flexible, but the more complex the structure, so there must be a degree

Demeter’s law

Also known as the Least Knowledge Principle (LKP) : an object should know the Least about other objects. The low coupling of classes is required

  1. Only communicate with friends. E.g. The teacher asks the monitor to count the students. The teacher should only be coupled to the monitor, not to the students.
  2. There is a distance between friends. A coupled class should not expose too many methods to other classes, or changes will require too much change. (High cohesion)
  3. If a method is placed in this class that neither adds to the relationship between classes nor negatively affects the class, then it is placed in this class.

The open closed principle

Open for extension, closed for modification

For example, you can change the getPrice() method of the original item class, or you can add a subclass, override the getPrice method, and use the subclass when the item is discounted through the high-level module. Obviously method 2 is a more flexible extension.

Benefits: The original code does not change, and you can reuse the original code

How to apply:

  1. Abstract constraints: Through an interface or abstract class, you can constrain a set of behaviors that may change and be open to extensions
    • Extension classes should not have public methods that do not exist in the interface
    • Parameter, reference object type use interface or abstract class whenever possible
    • The abstraction layer is as stable as possible
  2. Metadata controls module behavior Metadata: data used to describe the environment and data. For example, you can use the configuration file to change services.
  3. Develop project charter (develop and follow rules)
  4. Packaging changes

The changes are abstracted into the interface so that new changes can be generated into new instances of the interface and passed into the system. The 23 design patterns encapsulate change from different perspectives.

Design patterns

Patterns are a reusable solution that can be applied to common problems in software design.

Benefits of design patterns

  1. Patterns are proven solutions: tried and tested
  2. Patterns can be easily reused
  3. Patterns are expressive

23 design patterns

Stay tuned for more details on these 23 design patterns in our regular Android tech updates. Can’t wait to learn friends, recommended books “design mode zen”, “Android source design mode analysis and actual combat”