Design Patterns (buggy) Flashcards
What’s a design pattern?
Design patterns are typical solutions to commonly occurring problems in software design. They are like pre-made blueprints that you can customize to solve a recurring design problem in your code.
You can’t just find a pattern and copy it into your program, the way you can with off-the-shelf functions or libraries. The pattern is not a specific piece of code, but a general concept for solving a particular problem. You can follow the pattern details and implement a solution that suits the realities of your own program.
Patterns are often confused with algorithms, because both concepts describe typical solutions to some known problems. While an algorithm always defines a clear set of actions that can achieve some goal, a pattern is a more high-level description of a solution. The code of the same pattern applied to two different programs may be different.
An analogy to an algorithm is a cooking recipe: both have clear steps to achieve a goal. On the other hand, a pattern is more like a blueprint: you can see what the result and its features are, but the exact order of implementation is up to you.
https://refactoring.guru/design-patterns/what-is-pattern
What does a design pattern consist of?
Most patterns are described very formally so people can reproduce them in many contexts. Here are the sections that are usually present in a pattern description:
Intent of the pattern briefly describes both the problem and the solution. Motivation further explains the problem and the solution the pattern makes possible. Structure of classes shows each part of the pattern and how they are related. Code example in one of the popular programming languages makes it easier to grasp the idea behind the pattern.
Some pattern catalogs list other useful details, such as applicability of the pattern, implementation steps and relations with other patterns.
https://refactoring.guru/design-patterns/what-is-pattern
Why learn design patterns?
The truth is that you might manage to work as a programmer for many years without knowing about a single pattern. A lot of people do just that. Even in that case, though, you might be implementing some patterns without even knowing it. So why would you spend time learning them?
Design patterns are a toolkit of tried and tested solutions to common problems in software design. Even if you never encounter these problems, knowing patterns is still useful because it teaches you how to solve all sorts of problems using principles of object-oriented design. Design patterns define a common language that you and your teammates can use to communicate more efficiently. You can say, “Oh, just use a Singleton for that,” and everyone will understand the idea behind your suggestion. No need to explain what a singleton is if you know the pattern and its name.
https://refactoring.guru/design-patterns/why-learn-patterns
What are some criticisms of design patterns?
It seems like only lazy people haven’t criticized design patterns yet. Let’s take a look at the most typical arguments against using patterns.
Kludges for a weak programming language
Usually the need for patterns arises when people choose a programming language or a technology that lacks the necessary level of abstraction. In this case, patterns become a kludge that gives the language much-needed super-abilities.
For example, the Strategy pattern can be implemented with a simple anonymous (lambda) function in most modern programming languages.
Inefficient solutions
Patterns try to systematize approaches that are already widely used. This unification is viewed by many as a dogma, and they implement patterns “to the letter”, without adapting them to the context of their project.
Unjustified use
If all you have is a hammer, everything looks like a nail.
This is the problem that haunts many novices who have just familiarized themselves with patterns. Having learned about patterns, they try to apply them everywhere, even in situations where simpler code would do just fine.
https://refactoring.guru/design-patterns/criticism
What are the different types of design patterns?
Design patterns differ by their complexity, level of detail and scale of applicability to the entire system being designed. I like the analogy to road construction: you can make an intersection safer by either installing some traffic lights or building an entire multi-level interchange with underground passages for pedestrians.
The most basic and low-level patterns are often called idioms. They usually apply only to a single programming language.
The most universal and high-level patterns are architectural patterns. Developers can implement these patterns in virtually any language. Unlike other patterns, they can be used to design the architecture of an entire application.
In addition, all patterns can be categorized by their intent, or purpose. This book covers three main groups of patterns:
Creational patterns provide object creation mechanisms that increase flexibility and reuse of existing code. Structural patterns explain how to assemble objects and classes into larger structures, while keeping these structures flexible and efficient. Behavioral patterns take care of effective communication and the assignment of responsibilities between objects.
https://refactoring.guru/design-patterns/classification
What are the different Creational Design Patterns?
Factory Method (Virtual Constructor)
Abstract Factory
Builder
Prototype (Clone)
Singleton
What is the Factory Method design pattern?
Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
Also known as: Virtual Constructor
https://refactoring.guru/design-patterns/factory-method
What is the Virtual Constructor design pattern?
Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
Also known as: Virtual Constructor
https://refactoring.guru/design-patterns/factory-method
When is the Factory Method design pattern applied?
Use the Factory Method when you don’t know beforehand the exact types and dependencies of the objects your code should work with.
The Factory Method separates product construction code from the code that actually uses the product. Therefore it’s easier to extend the product construction code independently from the rest of the code.
For example, to add a new product type to the app, you’ll only need to create a new creator subclass and override the factory method in it.
Use the Factory Method when you want to provide users of your library or framework with a way to extend its internal components.
Inheritance is probably the easiest way to extend the default behavior of a library or framework. But how would the framework recognize that your subclass should be used instead of a standard component?
The solution is to reduce the code that constructs components across the framework into a single factory method and let anyone override this method in addition to extending the component itself.
Let’s see how that would work. Imagine that you write an app using an open source UI framework. Your app should have round buttons, but the framework only provides square ones. You extend the standard Button class with a glorious RoundButton subclass. But now you need to tell the main UIFramework class to use the new button subclass instead of a default one.
To achieve this, you create a subclass UIWithRoundButtons from a base framework class and override its createButton method. While this method returns Button objects in the base class, you make your subclass return RoundButton objects. Now use the UIWithRoundButtons class instead of UIFramework. And that’s about it!
Use the Factory Method when you want to save system resources by reusing existing objects instead of rebuilding them each time.
You often experience this need when dealing with large, resource-intensive objects such as database connections, file systems, and network resources.
Let’s think about what has to be done to reuse an existing object:
First, you need to create some storage to keep track of all of the created objects. When someone requests an object, the program should look for a free object inside that pool. … and then return it to the client code. If there are no free objects, the program should create a new one (and add it to the pool).
That’s a lot of code! And it must all be put into a single place so that you don’t pollute the program with duplicate code.
Probably the most obvious and convenient place where this code could be placed is the constructor of the class whose objects we’re trying to reuse. However, a constructor must always return new objects by definition. It can’t return existing instances.
Therefore, you need to have a regular method capable of creating new objects as well as reusing existing ones. That sounds very much like a factory method.
https://refactoring.guru/design-patterns/factory-method
When is the Virtual Constructor design pattern applied?
Use the Factory Method when you don’t know beforehand the exact types and dependencies of the objects your code should work with.
The Factory Method separates product construction code from the code that actually uses the product. Therefore it’s easier to extend the product construction code independently from the rest of the code.
For example, to add a new product type to the app, you’ll only need to create a new creator subclass and override the factory method in it.
Use the Factory Method when you want to provide users of your library or framework with a way to extend its internal components.
Inheritance is probably the easiest way to extend the default behavior of a library or framework. But how would the framework recognize that your subclass should be used instead of a standard component?
The solution is to reduce the code that constructs components across the framework into a single factory method and let anyone override this method in addition to extending the component itself.
Let’s see how that would work. Imagine that you write an app using an open source UI framework. Your app should have round buttons, but the framework only provides square ones. You extend the standard Button class with a glorious RoundButton subclass. But now you need to tell the main UIFramework class to use the new button subclass instead of a default one.
To achieve this, you create a subclass UIWithRoundButtons from a base framework class and override its createButton method. While this method returns Button objects in the base class, you make your subclass return RoundButton objects. Now use the UIWithRoundButtons class instead of UIFramework. And that’s about it!
Use the Factory Method when you want to save system resources by reusing existing objects instead of rebuilding them each time.
You often experience this need when dealing with large, resource-intensive objects such as database connections, file systems, and network resources.
Let’s think about what has to be done to reuse an existing object:
First, you need to create some storage to keep track of all of the created objects. When someone requests an object, the program should look for a free object inside that pool. … and then return it to the client code. If there are no free objects, the program should create a new one (and add it to the pool).
That’s a lot of code! And it must all be put into a single place so that you don’t pollute the program with duplicate code.
Probably the most obvious and convenient place where this code could be placed is the constructor of the class whose objects we’re trying to reuse. However, a constructor must always return new objects by definition. It can’t return existing instances.
Therefore, you need to have a regular method capable of creating new objects as well as reusing existing ones. That sounds very much like a factory method.
https://refactoring.guru/design-patterns/factory-method
What are the pros and cons of the Factory Method design pattern?
Pros:
You avoid tight coupling between the creator and the concrete products.
Single Responsibility Principle. You can move the product creation code into one place in the program, making the code easier to support.
Open/Closed Principle. You can introduce new types of products into the program without breaking existing client code.
Cons:
The code may become more complicated since you need to introduce a lot of new subclasses to implement the pattern. The best case scenario is when you’re introducing the pattern into an existing hierarchy of creator classes.
https://refactoring.guru/design-patterns/factory-method
What are the pros and cons of the Virtual Constructor design pattern?
Pros:
You avoid tight coupling between the creator and the concrete products.
Single Responsibility Principle. You can move the product creation code into one place in the program, making the code easier to support.
Open/Closed Principle. You can introduce new types of products into the program without breaking existing client code.
Cons:
The code may become more complicated since you need to introduce a lot of new subclasses to implement the pattern. The best case scenario is when you’re introducing the pattern into an existing hierarchy of creator classes.
https://refactoring.guru/design-patterns/factory-method
what
- this that