When to use which pattern? [closed]
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this questionAs a junior developper, i'm 开发者_如何学编程a bit confused about some design patterns. Sometimes, i just don't know which to use in which context.
For exemple, on creational patterns, i don't really know when to use:
- Factory
- Prototype
- Builder
Actually, i see some differences; but i also see that you can use multiple solutions like:
- Calling a factory that calls the appropriate builder that clones a prototype.
- Calling a factory that clones the appropriate prototype
- Calling a builder with the appropriate director
- ...
I mean, the result of these creations is at the end the same: you get your object instance.
I just wonder what kind of design you would use on different contexts (i guess it could be depending on performence needs, objects complexity, coupling...)
Also, I don't really see a big differences between a facade and a mediator, except the mediator calls different interfaces.
Same for chain of responsability, don't really understand why all implementations i see use chained lists. Can't this pattern be implemented with a simple List of handlers that we call successively?
That's why i'd like people to tell me in which concrete context you would use a GoF pattern, and also why you wouldn't use any of the other patterns that could have fit to the given problem (but probably in a less elegant way).
Thanks
Like many people when I first came across design patterns I realized that a lot of them were simply names for mechanisms I'd already used to solve design problems. The problem came first, then the solution. I never approached design patterns like they were puzzle pieces that needed to fit somewhere.
You're not really required to answer a problem with the name of a pattern as if it was an exam. The way to do it is to sit down and think about what you need your code to do and how it may change in the future. This is how we got to these design patterns anyway. People kept using the same tricks to solve a certain set of problems until eventually someone came along and gave those tricks names.
The only problem you have is lack of experience and that can't be fixed just by SO. As you write software you'll invariably get some things wrong. You'll discover that if you had done things this way, they would have been better. Incidentally this way has a name; "abstract factory", "adapter", "observer", whatever. In the future you'll know when and why to use it. For now remember the KISS principle. Don't complicate things that don't have to be complicated.
The fact that you're aware of design patterns before knowing how to use them means that you're a step ahead of most devs. Don't sweat it too much, just remember that next time you have a problem one of them might be an acceptable answer. Little by little you'll find out when a design pattern should be used and when it shouldn't.
What I want to stress the most in this answer, is my disagreement with this bit of another answer:
It's difficult (as you've noticed) to apply a pattern for the first time and understand what the benefits might be
You have to see a clear benefit the pattern will give before applying it. If that's not the case, don't use it, adding patterns to your code that don't give clear benefits will very likely fall in an anti-pattern scenario.
That's why i'd like people to tell me in which CONCRETE context you would use a GoF pattern, and also why you wouldn't use any of the other patterns that could have fit to the given problem (but probably in a less elegant way).
First, don't limit yourself to what you read there. The best aspects of the patterns is to enable you to acquire design options to several different scenarios.
Naturally there are scenarios that can be done in more than one way. Struggling choosing between 2 patterns in a very specific scenario? check them again, see what they said about the scenario and the benefits.
If you find yourself overwhelmed with the amount of patterns, give most of them a rest. Don't introduce all the patterns into your skills at once. Pick a related handful of those, and learn well when to apply them (read them again, search/ask for comparisons in SO/blog posts.
Always pay attention of how good the patterns you have applied respond to changes and how its the complexity of the code around them. Ask yourself the question on how those characteristics would be different with any of the other alternative patterns.
Finally, understand that you are best following an evolving code approach. Do your best in keeping your code clean, but don't obsess on finding a solution that won't ever have to change. Even with the patterns at hand, you will be taking some assumptions, that can impact which pattern you chose. Changes might not be in line with those assumptions, is a fact or life.
Read these 2 ebooks, can help you greatly on focusing how you design/develop/improve code.
Initially, I found the easiest way to learn patterns was to come across a situation that needed help (too complex to understand at a glance) and then implement it. It's difficult to understand why a pattern is beneficial until you have a problem that really calls for it.
An excellent resource for this is 'Refactoring to Patterns' by Joshua Kerievsky.
Using your creational confusion:
Factory: Creates an instance of several derived classes
Prototype: A fully initialized instance to be copied or cloned
Builder: Separates object construction from its representation
i had a case recently where i need to construct an object that implements an interface. i don't know, or want to know, what object (or objects) are used to implement that interface. Since i personally wanted to hide the objects, i had to use a Factory
:
public class TransactionValidatorFactory
{
public static IValidator CreateValidator(string RuleSet)
}
IValidator v = TransactionValidatorFactor.CreateValidator("Canada");
IValidator v = TransactionValidatorFactor.CreateValidator("UnitedStates");
IValidator v = TransactionValidatorFactor.CreateValidator("UnitedStates-Toyota");
IValidator v = TransactionValidatorFactor.CreateValidator("en-US");
And i've hidden the object(s) that are used inside the factory - as long as i get an interface i'm good to go.
i don't want to even have to see the objects that implement the interface - they are a complicated set of objects, that the person using them has no need to get into. Sometimes one object is required, sometimes it's multiple. That's a detail that i want hidden inside the factory.
But you look at the same situation, you seem to be focused on using a prototype
. This means you have to construct objects, set properties, and then clone
them as required. That's fine for you, when you know what object you want to use. You also have to write a .Clone()
method on your objects.
i don't want to see the objects, my objects don't support a Clone()
method, and i don't want to write one. That leads me back to the Factory
pattern.
My personal view is that design patterns on their own are generally of very limited use in the real world - I often see patterns sold as a fits-all solution "You should use the X pattern", when in fact the real world isn't as uniform as a textbook - software development is no exception.
Although understanding and recognising patterns is useful, don't fuss too much over trying to apply "design patterns" to real world problems, instead use knowledge of design patterns as inspiration when solving your own problems, for example although I often come up with solutions involving aspects which may seem similar to the factory pattern, I have yet to write a class with the word "Factory" in the name.
If it really was as simple as using design patterns all over the place then we'd all be out of a job! :-)
Factory: Creates objects without exposing the instantiation logic to the client.
Prototype: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
Use this pattern when creating an instance ( with new operator )is expensive. Generally clone()
is used to create an object from existing object.
Builder: Separate the construction of a complex object from its representation
Use this pattern when you have to create object with few mandatory attributes and many optional attributes. Providing constructor to create object with all mandatory and optional attributes is complex. Builder facilitates this construction process by following step-by-step method.
Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
Facade provides a simplified interface to complex system. It wraps a collection of APIs with a single well-designed API.
Mediator pattern defines an object (Mediator) that encapsulates how a set of objects interact. It enables many-to-many communication.
Related posts:
Design Patterns: Factory vs Factory method vs Abstract Factory
Keeping builder in separate class (fluent interface)
What is Facade Design Pattern?
Mediator Vs Observer Object-Oriented Design Patterns
精彩评论