DEV Community

Cover image for Design Patterns in Java

Design Patterns in Java

awwsmm profile image Andrew (he/him) ・3 min read

I thought it would be a fun to write a series of blog posts looking at different design patterns in Java. So the first thing I did was go to the Internet and try to construct a list of common design patterns. Being a type-A kind of person, I'd like to write an article for each design pattern that exists.

The list of patterns (which I constructed from a few top hits on Google) is below and it numbers over 100 distinct design patterns for Java programs.

So I'd like to have a discussion about design patterns in general. Is 100 too many distinct design patterns? Is this evidence of the expressiveness of Java? Or is it a failure on the part of the language that this many distinct use cases need to be explicitly mapped out? Is this too much templated code?

What are your opinions?

(Also, do you know of any design patterns that aren't on my list? Type-A.)

Java Design Patterns:

API Gateway Pattern [3]
Abstract Document Pattern [3]
Abstract Factory Pattern [1-5]
Action Pattern => Command Pattern
Acyclic Visitor Pattern [3]
Adapter Pattern [1-4]
Aggregator-Microservices Pattern [3]
Ambassador Pattern [3]
Async Method Invocation Pattern [3]

Balking Pattern [3]
Borg Pattern => Monostate Pattern
Bridge Pattern [1-4]
Builder Pattern [1-5]
Business Delegate Pattern [2-3]

Caching Pattern [3]
Callback Pattern [3]
Chain Of Responsibility Pattern [1-4]
Collection-Pipeline Pattern [3]
Command Pattern [1-4]
Command Query Responsibility Segregation (CQRS) Pattern [3]
CompletableFuture Pattern => Promise Pattern
Composite Pattern [1-4]
Composite Entity Pattern [2]
Converter Pattern [3]
Counting Semaphore Pattern => Semaphore Pattern
Criteria Pattern => Filter Pattern

Data Access Object (DAO) Pattern [2-4]
Data Bus Pattern [3]
Data Mapper Pattern [3]
Data Transfer Object Pattern [3]
Decorator Pattern [1-5]
Delegation Pattern => Proxy Pattern
Dependency Injection Pattern [3-4]
Dirty Flag Pattern [3]
Double-Checked Locking Pattern [3]
Double Dispatch Pattern [3]

Enterprise Integration Patterns: Aggregator [3]
Enterprise Integration Patterns: Message Channel [3]
Enterprise Integration Patterns: Publish / Subscribe [3]
Enterprise Integration Patterns: Splitter [3]
Enterprise Integration Patterns: Wire Tap [3]
Event Aggregator Pattern [3]
Event-Based Asynchronous Pattern [3]
Event-Driven Architecture Pattern [3]
Event Queue Pattern [3]
Event Sourcing Pattern [3]
Execute Around Pattern [3]
Extension Objects Pattern [3]

Facade Pattern [1-5]
Factory Pattern [1-2,4-5]
Factory Kit Pattern [3]
Factory Method Pattern [3]
Feature Flag Pattern => Feature Toggle Pattern
Feature Toggle Pattern [3]
Filter Pattern [2-3]
Fluent Interface Pattern [3]
Flux Pattern [3]
Flyweight Pattern [1-4]
Front Controller Pattern [2-3]

Guarded Suspension Pattern [3]

Half-Sync/Half-Async Pattern [3]
Handle/Body Pattern => Bridge Pattern
Hexagonal Architecture Pattern [3]

Intercepting Filter Pattern [2-3]
Interpreter Pattern [1-4]
Iterator Pattern [1-4]

Kit Pattern => Abstract Factory Pattern

Layers Pattern [3]
Lazy Loading Pattern [3]

Map-Reduce Pattern [3]
Marker Interface Pattern [3]
Master-Slave Pattern => Map-Reduce Pattern
Master-Worker Pattern => Map-Reduce Pattern
Mediator Pattern [1-4]
Memento Pattern [1-4]
Model-View-Controller (MVC) Pattern [2-4]
Model-View-Presenter (MVP) Pattern [3]
Module Pattern [3]
Monad Pattern [3]
Monostate Pattern [3]
Multiton Pattern [3]
Mute Pattern [3]
Mutex Pattern [3]
Mutual Exclusion Lock Binary Semaphore Pattern => Mutex Pattern

Naked Objects Pattern [3]
Null Object Pattern [2-3]

Objects For States Pattern => State Pattern
Object-Mother Pattern [3]
Object Pool Pattern [3]
Observer Pattern [1-4]

Page Object Pattern [3]
Partial Response Pattern [3]
Poison Pill Pattern [3]
Policy Pattern => Strategy Pattern
Private Class Data Pattern [3]
Producer-Consumer Pattern [3]
Promise Pattern [3]
Property Pattern [3]
Prototype Pattern [1-2,4-5]
Proxy Pattern [1-4]

Queue-Based Load Leveling Pattern [3]

Reactor Pattern [3]
Reader-Writer Lock Pattern [3]
Registry Pattern => Multiton Pattern
Repository Pattern [3]
Resource Acquisition is Initialization Pattern [3]
Retry Pattern [3]

Semaphore Pattern [3]
Servant Pattern [3]
Serverless Pattern [3]
Service Layer Pattern [3]
Service Locator Pattern [2-3]
Singleton Pattern [1-5]
Spatial Partition Pattern [3]
Specification Pattern => Filter Pattern
State Pattern [1-4]
Step Builder Pattern [3]
Strategy Pattern [1-4]
Surrogate Pattern => Proxy Pattern

Template Pattern [1-2]
Template Method Pattern [3-4]
Thread Pool Pattern [3]
Throttling Pattern [3]
Thread-Local Storage (TLS) Pattern [3]
Tolerant Reader Pattern [3]
Trampoline Pattern [3]
Transaction Pattern => Command Pattern
Transfer Object Pattern [2]
Twin Pattern [3]

Unit Of Work Pattern [3]

Value Object Pattern [3]
Virtual Constructor Pattern => Factory Method Pattern
Visitor Pattern [1-2,4]

Wrapper Pattern => Adapter Pattern / Decorator Pattern

Enter fullscreen mode Exit fullscreen mode

Discussion (18)

Editor guide
sayanarijit profile image
Arijit Basu • Edited

Well... I was reading the popular Design Patterns: Elements of Reusable Object-Oriented Software and another book on design patterns that claims to be the future version of this book and realized that we already use most of the concepts in our daily life. We just have to know what is called what. Of course, I found some unique and interesting patterns but that's about it.

Many of the patterns are only applicable to certain languages. Specially static typed languages with an attempt to make them more dynamic. So naturally dynamic typed languages don't need such patterns. For example, Python doesn't need builder patterns because by design every object has a builder method (__new__()) inbuilt in it which we can customize as per our requirements anytime we need to. Similarly, it doesn't need singletons as we can directly import objects from other packages.

However, such features make it a dynamic (flexible?) language at the cost of performance. Any static language using design patterns with an attempt to achieve the same flexibility is basically transforming itself to be more like a dynamic typed language.

I may be wrong in many cases, but that's my thought about it.

UPDATE: I would like to take back some claims I made in this comment. I just finished reading the book and realized how ignorant I was. I kept ignoring all the advantages this book let me gain. read this comment for more information.

lluismf profile image
Lluís Josep Martínez

Constructor method != Builder method

sayanarijit profile image
Arijit Basu • Edited

Actually constructor method is __init__() which handles initialisation of a new instance object. I'm talking about __new__() which handles building of an object. However, it's true that there are some builder patterns which are more that just customising the __new__() method (like all the factories). What I meant is that we don't have to think about this unless we hit the roadblock where it's really needed. And once we hit that roadblock, introducing a new pattern is much easier in this case as you have all the options you need for the change.

Most of the patterns I found in the book encourages us to move logics from compile time to run time as much as possible. Which is exactly what dynamic languages do where everything heppens on the runtime. This is what makes them flexible but at the cost of performance.

Thread Thread
awwsmm profile image
Andrew (he/him) Author

Very interesting! I might have to check out that book...

Thread Thread
sayanarijit profile image
Arijit Basu • Edited

Definitely do. I just finished reading the complete book and realized how ignorant I was.

I would like to take back my comments such as "We just have to know what is called what. Of course, I found some unique and interesting patterns but that's about it."

I didn't realize the advantages I gained before reading the conclusion part. The goal of this book was to give a name to the most commonly used patterns so that we can recognize them and refer to them more easily.

Before I started reading this book, I used to get confused when getting introduced to a new repository or code base. But now, it's much easier to learn a new code base. Because now, just by reading the name of a class or the name of the package it's inside, or the kind of relationship it has with other classes or objects, I know what it's supposed to do (like aha... it's an observer, and these are supposed to be strategy classes etc.). Still, I kept ignoring all the powers I gained until I finished the whole book.

I will write a more detailed post about what I gained from this book soon.

frothandjava profile image
Scot McSweeney-Roberts

I don't think the number of patterns has anything to do with Java (if it's not generalisable beyond Java I have to question if it's really a pattern). I think it has more to do with some people's proclivity to formalise the most trivial of things.

If you are going to go through all the patterns, you should double check that they really are patterns and also try and gauge how useful they really are.

awwsmm profile image
Andrew (he/him) Author

some people's proclivity to formalise the most trivial of things

...yeah that sounds like me

simbo1905 profile image
Simon Massey • Edited

I didn't see Model-View-ViewModel on your list which I wrote an article about back in 2011. The link to the Java code isn’t working in that article here is the code on GitHub. The readme has a broken link to the accompanying paper that IBM published that compares MVC, MVP, and MVVM in Java. Here is the PDF version.

Another one I didn't see is ”aggregate root” which is the key pattern in domain driven design. I coded that up in Java on GitHub and wrote a five part epic blog about it linked to from the readme.

I recently watched an interesting video which basically convincingly argues that “input-output plug-ins” to pure business logic is the key to clean architecture. Warning: the video spends the first 10 minutes talking about human evolution which seems utterly random but trust me watching the full video is well worth it.

I am not sure what the official name of the pattern in that video is. A quick google of ”plugin pattern” seems to be something on a smaller scale that is also not on your list.

simbo1905 profile image
Simon Massey • Edited

Also I don’t see the “transaction script” pattern which is identified as the default old school EJB stateless session bean pattern. The timeless classic book “Pojos In Action” by Chris Richardson describes it and why it is problematic. That book presents code in Java to implement domain driven design and the ideas in the timeless classic Eric Evans book. I don’t think you can buy an electronic version of Eric Evan’s masterpiece “domain driven design: tackling the complexity in the heart of software” but it is worth getting hold of a copy.

greenroommate profile image
Haris Secic

100 is too many we don't need to name every solution to a problem (pattern). Some of them are language fault but some of them are peoples fault.

Example Service layer pattern from my experience produced a lot of anaemic domain models as people used domain models as data models and did everything regarding business logic inside of a service. It was much easier in most of cases just to use controller -> repository -> domain do some logic -> return to controller -> client. It would be less code and easier to debug.

We need less patterns and more developers thinking about what do we actually need and stop cloning project architectures just because you are used to it. This mainly goes to employers, tech leads, and seniors.

Why do I need to use transformers and such in cases where DTOs will only be copy/paste some fields and ignore others. Maybe sometimes converting numbers to string. Isn't it easier to make DTO constructor that accepts object of some type and extract fields into DTO?

I saw Unit Of Work pattern while working with .NET Core. I never wanted to implement it nor did I need. Created simple repositories (in this case called by many anti-pattern) and used methods to fetch data to avoid wirtting same LINQ many times. Why would I write Unit Of Work? Just because someone wrote a blog about it and now all listed stuff must apply to me?

Hope you see the point I'm trying to make here.

awwsmm profile image
Andrew (he/him) Author

We need less patterns and more developers thinking about what do we actually need


lluismf profile image
Lluís Josep Martínez

Only a few of these patterns can be considered as "Java" patterns, specifically the J2EE ones ( The rest is a mixture of Gof patterns (based on Smalltalk I believe), Enterprise integration, SOLID etc. that are language agnostic. Maybe you meant Object Oriented design patterns?

simbo1905 profile image
Simon Massey

I would be wary of taking a “more is better” view of patterns.

If you are using a certain deployment architecture and technology stack I would recommended trying to find a minimal set of patterns and frameworks that are sympathetic to your choices.

Things change over time so it is a moving target. Patterns can become anti-patterns when new approaches supersede them. By way of example when I started out I was told that the Core J2EE Patterns were what I should use. Today I know that modern software shouldn’t be written that way.

Devs should learn the patterns that are idiomatic to their stack and architectures. It is a good idea to be on the constant lookout for upgrades that replace the need for an given set of patterns with something more productive.

janux_de profile image
Jan Mewes • Edited

Is 100 too many distinct design patterns?

Every design pattern is supposed to solve a particular kind of problem. So unless the list contains duplicates, I don't think it is too much.

On the other hand, 100 patterns are maybe too much to keep in mind. Further, for each pattern you have to spend time to understand it. Maybe also to memorize and practice.

Is this evidence of the expressiveness of Java? Or is it a failure on the part of the language that this many distinct use cases need to be explicitly mapped out?

It don't think that the high number of design pattern implemented with Java has something to do with the expressiveness of its syntax. Rather the business domains in which it is being used.

Some people claim that Kotlin solves a number of problems of the Java syntax. Still the underlying patterns are present, just with a more elegant syntax.

On the other hand a certain set of pattern depends on particular languages feature. E.g. the Converter pattern makes only sense if you have a type system. So while there is probably a subset, I'd expect a different set of commonly used pattern for other programming languages, say JavaScript or Erlang.

Is this too much templated code?

Only if people apply design pattern indiscriminately. Also one person's design pattern may be another person's anti-pattern. So I guess this question can't be answered.

samwho profile image
Sam Rose

Looking at your list, there are some patterns there that could be combined with other patterns. Strategy and command are fairly similar, as are the factory and builder patterns.

If you do end up writing these posts (and I really hope you do!) I'd love to see examples of the patterns used in the wild. 😀

swarupkm profile image
Swarup Kumar Mahapatra • Edited

Great Collection.
I would love to see blogs around Domain Driven Design, Event Sourcing, CQRS with Examples.
A list of DOs and DON'Ts as well.

I can get my head around this topic. Too Subjective and Less examples

sige profile image

Hi Andrew,
I just bumped into this article and registered here. I like the idea about a series on design patterns. Not sure how things work here, but I'm hooked on feature flags right now and would love to help with that part. Let me know if you are open for a chat. ;)

vitalipom profile image
Vitali Pomanitski

Hi Andrew, there's a series of books for that. We learn it here in MSc, Design Pattern from some guys from Siemens. They've got hundreds of design patterns there, so check em out.