Written at the beginning:
In the learning process, not only must we master skills proficiently, but theoretical digestion and absorption are also essential. Although I personally prefer learning technical things (short-term energy investment can quickly see results...), after reading many summaries of experience from seniors, I learned that theoretical things cannot be ignored. After all, theory has important guiding significance for practice. Understanding things related to "design" will have a subtle influence on "implementation". Although you cannot see gratifying changes in a short time, maybe one day when you look back and think "Oh~, it turns out that this good little habit of mine was learned from that book back then"
I. What are Design Patterns?
After going around in a circle, let's return to this topic again (ask yourself once before reading the book, and ask yourself again after reading it. The difference between the answers is the realization)
Before:
Self-question: What are design patterns?
Self-answer: They are some guiding principles for system design, but I write code every day now, so I probably won't need things at the design level.
Self-question: Oh, then what specifically?
Self-answer: Not clear, but I have seen some seniors' code, the structure is very complex, the kind that looks high-class at a glance, those should have used design patterns, so whether code applies design patterns should be the difference between experts and novices. After I become an expert, I won't believe I can't handle this stuff easily. Hmm, enough talking, I'm going to write code, accumulate project experience well.
After:
Self-question: What are design patterns?
Self-answer: Design patterns are theoretical knowledge extracted from experience in optimizing code structure. Applying mature design patterns can enhance code reusability, extensibility, and maintainability.
Self-question: You seem very professional. Okay, since design patterns have so many benefits, does that mean all designs that apply design patterns are good designs?
Self-answer: Of course not, we cannot use patterns just for the sake of using patterns. Design patterns must not be abused. After all, applying design patterns requires making some sacrifices (such as increasing the complexity of class structure...), so abusing design patterns will cause problems. Moreover, even if we have a hammer, we cannot treat all problems as nails, right?
P.S. Remember the summary of learning regular expressions: try not to use it if you can (avoid abuse to the maximum extent). Design patterns are similar. Don't try to fit everything into patterns. Only when we are very sure that we really need to use design patterns to optimize our design in the current scenario should we consider using design patterns (as for whether to use it or not, we also need to weigh the cost of refactoring against the benefit of optimization...)
II. Should We Use Design Patterns?
This is a question worth thinking about. After all, now that we already have a hammer, whether to use it naturally becomes a question, because not all problems can be solved with a hammer. Taking a step back, even if all problems can be solved with a hammer, we are not sure whether using a hammer is the best solution (for pulling nails, maybe using pliers would be better...)
When we want to put a certain design pattern into our code, it is best to weigh the pros and cons. Admittedly, the design flexibility that design patterns have will certainly bring some convenience to our subsequent maintenance changes. But which is more, benefits or drawbacks? We need to answer several questions before making a decision:
- Does our project involve almost no maintenance or no subsequent versions? Then is it still necessary for us to introduce design patterns?
- Is the scale of our project so large that we cannot do without design patterns?
- Is it appropriate to use this design pattern here? Is there a more suitable one?
- Must we use design patterns? Can we replace them with a few simple design principles?
- After introducing design patterns, the complexity of the code structure increases greatly. Can we accept the cost of refactoring?
If after careful consideration, you still think it is better to use design patterns, then, go ahead and use them, and enjoy the benefits that design patterns bring
III. Summary of Design Principles
Design principles are some simple guidance opinions without fixed implementations, so design principles are more flexible. Common design principles are as follows:
- Encapsulate change (extract the parts that are prone to change to reduce their impact on other parts)
- Use composition more, use inheritance less (composition is more flexible than inheritance)
- Program to interfaces, not implementations (using interfaces can avoid direct dependency on concrete classes)
- Strive for loosely coupled design between interacting objects (looser coupling means more flexibility)
- Classes should be open for extension, closed for modification (open-close principle)
- Depend on abstractions, not concrete classes (reduce direct dependency on concrete classes)
- Only talk to friends (Law of Demeter)
- Don't call me, I will call you (Don't call me, I will call you back. A major principle of Android development)
- Classes should have only one reason to change (Single Responsibility Principle)
If a problem can be solved with design principles, don't use design patterns (why use a butcher's knife to kill a chicken...), because design principles are more flexible and lighter to implement (no need to consider the rules and frameworks of patterns...)
IV. Summary of Design Patterns
| Name | Characteristics |
| Strategy Pattern | Encapsulates replaceable algorithm steps into individual algorithm families for dynamic selection at runtime |
| Observer Pattern | Defines and maintains a one-to-many relationship between objects |
| Decorator Pattern | Establishes decorators and decoratees with a common superclass to achieve dynamic extension of functionality |
| Factory Pattern | Encapsulates the object creation process, including Factory Method Pattern and Abstract Factory Pattern |
| Singleton Pattern | Used to create a unique object (such as database connection objects, thread pool objects, etc.) |
| Command Pattern | Encapsulates method call details, decouples requester and executor |
| Adapter Pattern | Used to achieve conversion between different interfaces |
| Facade Pattern | Provides a simple and easy-to-use high-level interface for complex subsystems |
| Template Method Pattern | Used to encapsulate algorithm skeleton (process), certain steps are implemented by subclasses |
| Iterator Pattern | Used to encapsulate traversal details |
| Composite Pattern | Provides a hierarchical structure that allows us to ignore differences between objects and collections of objects, treating them equally |
| State Pattern | Encapsulates all actions in state objects, state holders delegate behavior to the current state object |
| Proxy Pattern | Separates caller and callee (different from executor) by inserting a third party (proxy object) |
| Compound Pattern | Combines multiple patterns together to form a "framework" to solve general problems |
| Bridge Pattern | Decouples abstract control classes and concrete implementation classes through composition, allowing abstract layer classes and implementation layer classes to vary independently and opposite to each other |
| Builder Pattern | Used to encapsulate the construction process of composite structures (tree structures). Similar to the Iterator Pattern, it hides the internal implementation of composite structures and only provides a set of interfaces for creating composite structures |
| Chain of Responsibility Pattern | Allows a request to be processed sequentially by a set of receivers, similar to how Android handles requests: after a receiver captures a request, it can return true to consume the request, or return false to pass it to the next receiver (observer) in the receiver queue |
| Flyweight Pattern | Abstracts object management layer to uniformly manage a large number of objects of the same type, to reduce the number of runtime object instances and reduce memory consumption |
| Interpreter Pattern | Used to create interpreters for simple languages, directly mapping grammar rules to various classes. Simple structure, but low efficiency |
| Mediator Pattern | Introduces a mediator to encapsulate complex interactions between multiple objects, to reduce dependencies between peer objects (at the same level in the class structure) |
| Memento Pattern | Supports saving and restoring object state, and encapsulates object state data, independent of client code to provide protection (in Java, can be combined with serialization and deserialization technology to implement this pattern) |
| Prototype Pattern | Uses existing objects as prototypes to get new objects through clone (to simplify the creation process of new objects) |
| Visitor Pattern | Adds new operations to composite structures without frequently changing the composite structure |
V. Object Oriented Design
The problem that has always accompanied OOD is "trade-off" (or "compromise"). The simplest example——should we use design patterns?
- Using them means generating complex class relationships, multi-layer abstractions. We will sacrifice readability for extensibility, maintainability, or other characteristics
- Not using them means we don't need to refactor existing code (or don't need to spend too much time on complex designs), but we won't enjoy all the benefits of using design patterns
Choosing one of the two is a "trade-off", or creating a third option (such as using design principles), which is a "compromise"
Written at the end: About "Head First Design Patterns"
I rarely write book reviews because everyone's preferences are different, so it's not good to make recommendations (sometimes even liking a book is just because you like the author's writing style, thus unconsciously thinking the book content is good...)
This book was recommended by a senior. After reading it, I felt that most chapters were very well explained, both detailed and accessible. But I felt that some chapters were not very good (for example, the Strategy Pattern example in Chapter 1 is not very appropriate, and the details of the remote proxy part later are unreasonably expanded)
Overall, as an introductory book, "Head First Design Patterns" is still quite good. Personal feeling, for reference only
No comments yet. Be the first to share your thoughts.