The “implementation” or “examples” section of any pattern discussion holds several goals (and a few “anti-goals”):
- Be able to put a concrete-ish example in front of people seeking such. It’s hard to understand exactly how the pattern is supposed to work without pictures or code. I am not great with graphical tools, so for me it’s easier to use code to provide that demonstration.
- NOT to expect “ready-made code” for reuse. Patterns are not drop-in building blocks that can save you time and energy when doing your own implementation. These examples are here to demonstrate a few techniques around implementation, but attempts to re-use the code directly will probably always meet with failure at some level.
- Demonstrate how to do certain things idiomatically within a particular language. Each language brings with it a particular idiomatic style or feature set that may shape how one might use a particular pattern. I am not an expert with all of these languages below, but part of this exercise (for me) is to learn (and document) how to exercise the idioms of a particular language using the pattern as a scaffold upon which to hang it.
- Provide a mechanism by which to concretely compare and contrast one pattern against another. Is a Strategy really all that close to a Command? Having concrete examples of each allows for a certain amount of comparison-and-contrast, and hopefully sparks some good discussion around when to use each.
- NOT to suggest that one language is “better” than another. Any such qualitative judgment around one language over another is entirely in the eyes of the beholder; no such judgement is intended from me, and any attempt to use this exercise as a means to judge one language more harshly than another will quickly earn this author’s scorn. Different languages chose to do things in different ways for very good reasons; if you cannot explain the reasons, then you have no business offering up the judgement.
In general, there’s a long list of languages I will use to define some example implementations of the patterns in the catalog. Note that while this isn’t an “ordered” list, meaning I will probably do implementations in a seemingly-random order, the hope is that when this is all said and done, the list of pattern implementations will range across the following:
- Swift: an imperative, strongly-typed object-oriented langauge for the LLVM (iOS/Mac OS X) platform. Granted, Swift does have some functional features to it as a language, but by this point not much more than that of what we see from C#, Java or C++.
- C#: an imperative, strongly-typed object-oriented language for the CLR platform.
- F#: an object/functional, strongly-typed language for the CLR platform.
- Java: an imperative, strongly-typed object-oriented language for the JVM platform.
- Scala: an object/functional, strongly-typed language for the JVM platform.
- C++: an imperative, strongly-typed object-oriented language for native platforms. Specifically, I will be looking for opportunities to incorporate C++11 and C++14 features into the pattern implementations, particularly since when the original GOF book came out, C++ was missing a lot of the features we find there today: templates (and the STL), exceptions, code blocks, and more.
I also plan to explore some other languages, sometimes as an intellectual exercise (and as a way to practice writing code in those languages), sometimes because I think the language is going to gain more traction, and sometimes just because I’m intrigued. That list includes, but is not limited to:
- Rust Same story (for me) as Go.
- Clojure: a Lisp; a weakly-typed functional language with a few object-interoperability features for the JVM platform. My Clojure Fu is not as strong as I would like it to be, so I will periodically attempt a pattern in Clojure just to experiment and see how well/poorly I can implement said pattern.
- Yeti: an ML clone; a functional, strongly-typed for the JVM platform.
- Kotlin: an imperative object-oriented language for the JVM. I’ve looked briefly at Kotlin, and largely because of the proposed association with using Kotlin to write Android code, I want to spend more time working with it.
- Scheme: one of the original Lisps; a functional, weakly-typed interpreted language.
- Haskell: one of the original pure functional languages; compiles to native platforms. My Haskell is not great, however, so this will definitely be a learning exercise for me.
- Frege: a Haskell clone; a functional, strongly-typed language for the JVM platform. Quite frankly, if I’m going to learn a Haskell, I’ll probably do it in Frege instead, since that runs on a platform I often care deeply about. Two birds, one stone.
- Lua: an imperative, untyped, object-ish interpreted language. Lua is a scripting language with only a very loose notion of objects (no inheritance to speak of, no class types to speak of), whose great claim to fame is that it is ridiculously easy to embed inside of a native application. (This is why Lua shows up so frequently inside of game engines.) This represents a pretty strong challenge to the patterns: can a language that lacks one of the core features the Gang-of-Four relied on—inheritance—still implement some of these patterns?
- Erlang: a functional, strongly-typed language for the Erlang platform.
- Elixir: a functional, weakly-typed language for the Erlang platform. Like some others on this list, Elixir has some features that allow it to take advantage of some of these patterns.
- Objective-C: a weakly-typed object-oriented language for native platforms. ObjC is more or less on its way “out” as the language of choice for Mac OSX/iOS, but I may periodically tinker with it as an implementation language, just for fun.
And of course I reserve the right to add a few more languages to the mix, if they’re interesting. Because, in a lot of ways, while I hope that readers get a lot out of this, this whole exercise is more for me than anybody else.