AI Translated Document
- This document was translated using an AI translation tool.
- Due to the nature of AI translation, some sentences or terms may be interpreted differently from the original intent.
- There may be mistranslations or inaccuracies, so please refer to the original text or consider additional review if accuracy is critical.
- Your suggestion for a better translation would be highly appreciated.
Original Document in Korean
Design Patterns Are Meant to Be Modified¶
HJ, Ph.D. / Software Architect (js.seth.h@gmail.com) Draft: April 2022 / Revised: December 2025
[Authorโs Intent] This article was written to highlight why treating design patterns as the โcorrect answerโ can be a dangerous choice that strips away the context of the problem.
Executive Summary¶
- Design patterns are not the answer, nor are they ready-made solutions.
- Patterns are organized summaries of classes and their communication structures that are repeatedly used as solutions.
- While we focus on the extensibility of patterns, nothing changeable is ever decided.
- The real essence is the fixed "roles and collaboration structures"โthe skeleton of information processing embedded in each pattern.
- The skeleton of processing is a device that restricts the flow of information processing, and is essential for the existence of replaceable parts.
- The ultimate use of patterns is to modify them based on the skeleton to fit the situation.
- To modify, you must understand the invariant collaboration structure.
- Most people do not truly understand the essenceโrole allocation and collaboration structure.
- Grasp the coercive power of what is fixed.
- First, apply design patterns where appropriate.
- And since each project has a different balance point, the ability to "modify" patterns rather than use them "as-is" is more advantageous.
Preface¶
Design Patterns: Elements of Reusable Object Oriented Software์ ์๋ฌธ์์...
One thing expert designers know not to do is to solve every problem from first principles. Rather, they reuse solutions that have worked for them in the past. When they find a good solution, they use it again and again. Such experience is part of what makes them experts. Consequently, you'll find recurring patterns of classes and communicating objects in many object-oriented systems. These patterns solve specific design problems and make object-oriented designs more flexible, elegant, and ultimately reusable. They help designers reuse successful designs by basing new designs on prior experience. A designer who is familiar with such patterns can apply them immediately to design problems without having to rediscover them.
GoF did not "invent" design patterns, but rather discovered and organized structural solutions that repeatedly appeared in real-world success stories. In other words, patterns are not fixed as "correct answers" from the start, but are always meant to be adapted to the situation.
In short, design patterns are not meant to be memorized and used as-is, but to be used as a foundation for modification.
Are They the Answer?¶
In software development, design patterns are often regarded as the product of accumulated experience and wisdom over a long period. Many developers learn patterns, apply them to projects, and seek better structure and maintainability through them. However, those new to patterns often misunderstand them as "the answer." It can feel as if following textbook examples exactly is the only way to design correctly.
But patterns are about discovering commonalities from past experience.
In reality, the essence of design patterns is not a "standardized solution." Patterns are collections of solutions to recurring problems, offering a simplified model and a general solution. They are not a universal key that fits every situation perfectly from the start. Each project has different requirements, constraints, team capabilities, and technology stacks, so applying patterns as-is can actually cause problems.
For example, the Singleton pattern is useful for ensuring the uniqueness of an object, but in multithreaded environments or test code, it can cause unexpected side effects. In such cases, modifying the pattern or applying only part of it is a wiser choice. In other words, the original purpose of patterns is to be "modified."
Of course, you still need to memorize them...
What Is the Essence of a Pattern?¶
Before discussing the essence of patterns, let's briefly touch on what software is.
Since the Turing machine, software has essentially been about the "flow of computation." Despite conceptual advances like assembly, imperative languages, and object orientation, we are still coding computational procedures. Design patterns are simple models that organize structural solutions to recurring problems in processing flows across many projects, and as the GoF's classification shows, most of these problems stem from the need to adapt software to changing elements.
Structural Solution - What Does 'Structural' Mean...
'Structural' here refers to the forces that arise from a more macro perspectiveโroles and status, resource allocation, conventions and rules, and relationships. In fact, this word alone deserves a separate document...
However, nothing changeable is ever decided. What actually gets decided is the 'fixed, unchanging part.' In other words, the core to focus on in design patterns is always embedded in the fixed part. Fixed inheritance structures, function signatures, return types, and loop structures restrict the flow of information processing and exert strong coercive power. At the same time, this coercive power is essential for accommodating replaceable subsystems.
A glass half empty is also a glass half full.
Also, the fact that design patterns were discovered through observation of commonalities proves that every project applied them a little differently, each with its own color.
Patterns were never the answer from the start, and the core is the "classes and their communication structures" embedded in the fixed part. Reusing that structure was one of the ultimate goals.
In Fact, Most Developers Do Not Understand the Essence of Each Pattern¶
Let's take an example.
First, consider the Strategy pattern, which is a behavioral pattern. The main point of the Strategy pattern is "to encapsulate behavior so that it can be changed at runtime." The concrete strategy (algorithm) can change as much as needed, but the collaboration structure between Context and the Strategy interfaceโparameters and return typesโdoes not change. This structure of promises is the skeleton of processing. As long as the developer maintains this skeleton, it is possible not only to pass simple values, but also to pass external system connections like database access, or to process only success/failure in the return, and set all necessary results through the reference object passed into the strategy pattern (a kind of Strategy-Builder combination).
Meanwhile, the Template Method pattern is also a behavioral pattern. The key point of the Template Method pattern is that the superclass defines the overall flow of logic as a template, and the subclasses implement the details. The flow of logic does not change. Here, the specificity of this flow is very important: the Template Method actually predefines the types and delivery system of data between steps (e.g., the result of step 1 becomes the input of step 2). In general explanations, the Template Method is introduced as allowing subclasses to freely change behavior.
However, in reality, the procedural skeleton defined by the superclass acts as a very strong constraint. The format of input/output, the structure of data transfer between steps, and the order of calls are all strongly fixed, so the room for modification is actually very narrow, not only compared to the Strategy pattern but in absolute terms as well.
On the other hand, the Strategy pattern generally only enforces a single function signature, so it is much more flexible. Instead, the Template Method allows the parent class to provide common processing and to build a system dependent on it, but in the Strategy pattern, while the parent can provide common functionality, it cannot enforce its use, so you cannot build a system where common elements must always be used.
There is also a tendency to focus on the Context, the caller of the strategy routine, in the Strategy pattern, because the Context can change the concrete implementation to change functionality. However, the Template Method also requires someone to call it, and the Abstract Template Class cannot call itself, so naturally there is a Context, which has the ability to change the concrete implementation.
Since GoF's Design Patterns in 1994, many books have been published. But I have yet to see a book that points out that the Template Method actually requires a Context.
If you accurately identify the fixed and variable elements of these two patterns, you will see that they are more similar than you think, yet their differences are significant. This is because the coercive power embedded in the fixed part acts differently in each case. The two patterns show a certain compatibility, but also distinctly different coercive power and extensibility.
The Coercive Power of What Is Fixed¶
The primitive form of a program is ultimately hardcoded computation. Its essence is a procedural set of fixed commands, but we added parameters to apply the same computation to different data. Likewise, we have granted freedom through structural solutions for various variations and branches. If a skilled architect does not have to compromise on cost, they can find ways to grant as much freedom as desired. But through practical adjustment, the parts that do not need freedom remain fixed, forming the foundation for free extension. In other words, the coercive power that comes from a fixed foundation becomes a component that guarantees predictability, stability, and reliability.
In real-world development, there are also undetermined future strategies, and sometimes you prepare for future changes in advance. To accommodate such unknowns in the system, you must set certain rules. In other words, extensibility is established on rules for interoperability. That is, you must necessarily set a compromise pointโrules, and communication between rolesโand coercive power determines what extensions are acceptable.
The more coercive power, the easier it is to predict, the less likely there are bugs, and the faster development can proceed. If you only care about implementation stability, the simplest hardcoding is most advantageous, but that does not mean you can achieve market adaptability or customer satisfaction. Therefore, software always needs a compromise to balance coercion and variability, and every project must set its own unique compromise point.
Whether it's a design pattern, architecture, or API, when deciding on any element, you must consider the coercive power that will result. If you can view things from this perspective, you can identify and apply the coercive power of each design pattern.
Conclusion¶
Design patterns show best practices for how much of the information processing flow to fix, what promises to put at the boundaries, and what coercive power can be exerted. However, each pattern shows quite different coercive power even with very subtle differences. Therefore, when introducing a particular pattern, you need to understand exactly what you are fixing and what promises are being made. Based on that understanding, you should choose patterns to secure both stability and extensibility in your software.
Meanwhile, each project pursues a different direction, so simplified best practices like design patterns may not fit exactly. Also, design patterns present models, and depending on the responsibilities of an object, it may be appropriate for a single class to apply two or three patterns at once. Therefore, it is much more advantageous to understand each design pattern precisely, maintain the core skeleton, and develop so that the object exerts modified coercive power according to its responsibilities.
See Also¶
- Software Architecture Is Decision-Making, Not Imitation - Whether it's a design pattern, architecture, or API, it's about understanding and applying, not imitation.
- Software Architecture Is Determined by Invariants, Not Extensibility - Variability and extensibility stem from fixed invariants.
- You Must Follow Intuition to Make Code Readable, and Readable Code Is Easier to Modify - Knowledge affects readability.
- Architecture Is a Structural Solution - What is a structural solution?
Author¶
HJ, Ph.D. / Software Architect
(js.seth.h@gmail.com)
https://js-seth-h.github.io/website/Biography/
Over 20 years in software development, focusing on design reasoning and system structure - as foundations for long-term productivity and structural clarity.
Researched semantic web and meta-browser architecture in graduate studies,
with an emphasis on structural separation between data and presentation.
Ph.D. in Software, Korea University
M.S. in Computer Science Education, Korea University
B.S. in Computer Science Education, Korea University
)