Design patterns implemented in Java
github.com
github.com
This needs to be at the top, in the introduction. Especially in Java and C#, I've seen far too much "over-patterned" code, in contrast to the opposite.
The thing is, during the class we understood what the patterns were. However, since the actual programming project was comparatively small we didn't actually understand what a need for following these patters looks like. We didn't see a case where the simple way just didn't cut it, we were simply told to use them because they are good. The effect of this is that, unless someone with experience then comes and mentors you, you will overengineer all of your solutions because you don't know any better. We were taught the patterns but didn't understand the reasons. And I suspect many other engineers have had similar experiences
ps: I also forgot to say, even though I'm a fp head these days, imperative C felt fun, that is if you carefully stay into state -> state mindset ;)
I'd argue that Design Patterns mostly appeared because of Java. Because of people hitting the wall with Java; Java does not allow metaprogramming; Java did not allow class members (it allows instance members); Java does not allow multiple inheritance; Java has a cumbersome and underpowered exception handling system; Java's OOP is really strict and limited; no real functions that can be passed around (not even in Java 8); recursion can't use tail call optimization... etc etc
because of ALL this, then developers had to resort to applying the same workarounds. And such workarounds were collected, tagged, and proposed as
Design Patterns
by the gang of four.But seriously, if the authors write,
"All designs should be as simple as possible. You should start with KISS, YAGNI (...)"
Then they should be looking at alternatives to Java in the first place. It's 2017 and there are other alternatives that even run in the JVM (if this is a requirement).
The GoF book predates the public release of Java. The code samples in GoF are in C++ and Smalltalk.
Correct me if I'm wrong, but Java 8 does allow functions to be passed around. E.g., if a function takes as input a Runnable, I can pass a no arg lambda expression as input.
https://www.tutorialspoint.com/java8/java8_functional_interf...
Beyond that, by at least 1.4 you could pass methods using the reflections API, though that was kludgy in a lot of ways.
Fyi... "Design Patterns" in 1994 predates Java 1995.
Design patterns in some form have been around as long as computers have been around. Independent teams of programmers notice a repetition of code or a higher-level idea and they make it a convention. E.g. the "observer" pattern was something Smalltalk and Objective-C programmers did more than a decade before Java. Before "Design Patterns" became a meme/book, different teams used different vocabulary. Maybe they'd call it the "event watcher code convention" instead of "observer pattern". DP was a book of past practices gathered from the real world and it got everyone to converge on the same vocabulary to label what they were already doing.
The language most of the examples are written in, C++, does allow multiple inheritance and metaprogramming, and a bunch of other stuff Java does not allow. The patterns are still useful in C++ despite those features, which is why C++ developers came up with them in the first place.
Sorry but I do stand on my criticism of Design Patterns as applied today.
> The language most of the examples are written in, C++, does allow multiple inheritance and metaprogramming,
You're being very generous with C++ if you consider it does allow metaprogramming. It does not, if we compare it with the languages that make good use of metaprogramming: Lisp, Scheme, Racket, and now Julia.
Just as assembly language is also turing complete, but there is also a ton of usability difference between it versus C/C++, in favor of C/C++ and with little performance penalty.
A language can be Turing Complete, yet do only pure calculation plus I/O strictly in Roman numerals on two predefined streams.
Good luck decoding a JPEG with that, right?
Turing Complete means that you can calculate any partial recursive function (given some suitable input encoding).
For instance, in pure Lambda Calculus that has only functional terms (no numbers), we an make integers out of function using "Church numerals" and then calculate functions over these numbers. No amount of such calculation will produce an integer object, though.
Similarly C++ template cannot calculate any C++ syntax whatsoever, in spite of Turing Completeness. You get template functions and template classes; that's it.
Ok, so you think recursion is unnecessary in a multi-paradigm language.
Which implies also that multi-paradigm languages shouldn't be really multi-paradigm languages... Java, by the way, is hardly a multi-paradigm language.
And you imply that the reason one uses recursion is because one can't "write iterations as ... iterations".
You should realize that recursion is used whenever expressing the problem in a recursive way would make the problem easier to program and/or clearer to express, etc. Not because of recursion being fancy or fashionable.
Recursion is a computer science technique, not a "Design Pattern".
https://github.com/iluwatar/java-design-patterns/tree/master...
And here is a second source if you don't believe me or iluwatar
>In functional programming, a monad is a design pattern that defines how functions, actions, inputs, and outputs can be used >together to build generic types,[1] with the following organization: > > Define a data type, and how values of that data type are combined. > Create functions that use the data type, and compose them together into actions, following the rules defined in the first >step.
https://en.wikipedia.org/wiki/Monad_(functional_programming)