views:

162

answers:

6

Hello,

As 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

A: 

I highly suggest you to implement a design pattern when you face a situation when it can solve your problem.

Applying a solution to a problem before you encounter it can be counterproductive.

Pierre 303
I'm not sure if this answer is meant with a degree of sarcasm, but I don't agree anyway. It's just as valid to use a design pattern *to solve a problem you anticipate you may possibly encounter in the future* as to solve an immediate problem. Isn't that kind of the point of loose coupling?
fearofawhackplanet
Yes I have the exact same opinion. That's why "can" is in italic.
Pierre 303
+2  A: 

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.

Steve Jackson
+1 for the clarification posted in my answer's comment. I suggest to edit that part of this answer, to be clearer in that. Maybe more in line with the comment: its hard to understand why a pattern is beneficial until you have a problem that really calls for it.
eglasius
Good call. Thanks for the help.
Steve Jackson
A: 

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! :-)

Kragen
+10  A: 

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.

Manos Dilaverakis
+1 specifically for "You're not really required to answer a problem with the name of a pattern as if it was an exam"
eglasius
+1 for KISS (xtra chars)
Icode4food
+1 for *"simply names for mechanisms I'd already used".* A pattern is not something you have to use. Someone simply decided to take the time to write down all the solutions and have been "invented" over and over - and name them. By reading GoF you're getting a head-start on "inventing" your own solution - it might have been invented. They may already be obvious, but now they have a name.
Ian Boyd
And if i could i'd +1 again for the rest of the answer.
Ian Boyd
This is an infinitely better answer than the chosen answer. I would expound on it, but it says everything perfectly.
EricBoersma
+3  A: 

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.

eglasius
I think we're in agreement, honestly. One can't apply patterns without having a benefit in mind. However, I certainly couldn't understand 'why' a pattern was beneficial until it solved a problem that was bothering me. Up to that point, it was a diagram in a book. You can write a whole lot of code before you ever need an Singleton. That doesn't stop everyone who's ever read GOF from trying to squeeze a Singleton in every time they want an excuse to use a global variable.
Steve Jackson
@Steve I completely agree with what you say in this comment. The way I read that part of your answer initially was like: you'll realize the benefits the more you use them. And that's how we get the situation you just described, people trying to use patterns all over for no reason. I understand now its not what you meant.
eglasius
+1  A: 

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.

Ian Boyd
As you give to the factory a parameter that will lead the factory to create a specific "hidden" object, couldn't you also pass a parameter to a builder (that's called a director here) that would return the wanted object (implementing your interface) ? Perhaps in this case the builder is also some kind of factory... I guess It could add some useless complexity but it would almost do the same
Sebastien Lorber
Redoing to code use a `Builder` patter doesn't help me, and it makes things more complicated. i would use a `Builder` when constructing the various objects is a complicated process - complicated enough that a write an entire class designed to construct it for me. i don't need that - just `new CanadaTransactionValidator()`. Actually, i do have a few cases where one of the returned `Validator` objects is implemented using four or five child objects. But even then the construction is not complicated enough that i would need to create a class that specialzes in creating the object.
Ian Boyd
It's also important to realize, in my case, that a can't use a `Director`/`Builder` pattern; it doesn't fit. You pass a `Builder` to a `Director`. The `Director` calls methods on the `builder`, which then creates the object that the builder needs. This means that i would need a `Builder` class for every kind of resulting object i need. Picking the right object (and combination of objects) i need is the job of run-time code (in a factory), rather than pre-writing a Builder for all possible requests.
Ian Boyd
In my real system, the interface returned can be backed by 25 different combinations of objects. i don't want to create 25 builders. a) it's overkill; the construction is not so complicated that i have to abstract into a dedicated builder, but also b) i'm too lazy to do that
Ian Boyd