Learn Design Patterns Theory
This is a supplement to the design patterns playground tool. I will continue adding to this and adding more patterns to the design patterns playground. If you notice mistakes or want specific patterns, or different tutorials, let me know.
I am going to use some keywords in this article that you might not be familiar with. These are covered in the glossary at the bottom of this article.
Design PatternsPermalink
Creational PatternsPermalink
Factory MethodPermalink
What is itPermalink
- Very basic pattern that allows you to abstract away parsing and other logic related to creating a group of similar objects.
Why use itPermalink
When refactoring the creation of similar objects, by having the factory method, you can make small changes that will apply to many things. It also gives much better visibility and control of how objects are created because it is all grouped into one block of code.
Builder PatternPermalink
What is itPermalink
- Slightly more complex pattern that involves builders and directors.
- Builders act as blueprints or receipts that implement a common interface (ie. houses and apartments could each have a builder which controls what type of foundation they have, what type of walls they have and what roof they have).
- Directors take a builder, construct it and return an object that was built.
- You can have multiple director methods which construct builders differently. For example, if it never rains where you live and you want roofless houses, you could have a regularDirector and rooflessDirector and when the regular one takes in either of those builders, it will build the regular house/apartment, whereas the roofless director would also build both, but leave out the roof.
Why use itPermalink
This pattern allows you to build a variety of products that are built with similar steps but are products that might never interact with each other. For example, if you want to build a phone and smartwatch, you could use different directors (one for phones and one for watches) and then one builder could mediate the parts for each. Additionally, you could change the type of screen, type of charging port etc in the builder, and construct with the same director to create a completely different phone/watch.
This article will continue being updated over time…Permalink
Next update on 3 July 2025
GlossaryPermalink
Java TerminologyPermalink
Classes and ObjectsPermalink
A class is a definition of some concept that is meaningful in your code. For example, a collection of wheels, engine, doors, and windows might be meaningful to your cod so you create a class called Car and define some attributes (features of the car e.g. number of wheels, engine type etc) and methods (behaviours of the car e.g. drive(), park(), open_door()).
An object is an instance of a class. So, a class could be a definition of a car, whereas a specific car itself is an object. You can create multiple objects of the same class, each with the same definitions (they all have wheels, an engine, doors, and windows) and they will each have the same behaviours (they can all drive(), park(), open_door()). Based on the values of the attributes that you set, and transformations you make by calling methods on an object, you may end up with a completely different behaviour for 2 separate car objects. e.g. if car1 calls park() and then calls open_door(), then the doors will be unlocked. Whereas with car2 which calls drive() and then calls open_door(), it would return an error because you should not be able to open the door when the car is driving.
Attributes and MethodsPermalink
Attributes are the variables that are owned by a class in Java. Methods are the functions that are owned by a class in Java.
Access ModifiersPermalink
In Java, access modifiers determine what information about a class another class can interact with. To keep this simple, you can assume a package is a folder containing Java files (and that different folders are different packages).
A brief summary of meanings and definitions:
| Access Modifier | Meaning | Typical Use case |
|---|---|---|
private |
Can only be accessed inside the class definition | Attributes of the class, helper functions |
default |
Used when no access modifier is specified. Any code in the same package can access it | Situations where we want a single definition/constraint across a package that is not applicable in other packages |
protected |
Any code in the same package can access it, or any code outside of the package where the class with the protected member is implemented | Situations where you want an attribute or method to be defined/implemented (e.g. an abstract method) but do not want to expose the member to other packages that may just use the object |
public |
Can be accessed by any class in any package | Methods that anyone should be able to call to read/modify/transform attributes or transformations on attributes of an object |
Note that the above is simplified and there are nuances that are good to understand if you already understand what is going on. Refer to this website on access modifiers to get a more in-depth overview.
Coding PrinciplesPermalink
Abstraction and EncapsulationPermalink
Abstraction and encapsulation seem to have very similar meanings but they small differences lead to much larger consequences in why they are important.
AbstractionPermalink
DefinitionPermalink
Abstraction refers to hiding complexity from a user who does need to know about the complexity to make use of a product. This is an extremely common concept both within and outside of technology. Whenever you use a complex device such as a laptop, you don’t need to understand how the cpu or wiring works.
BenefitsPermalink
Abstraction is used to hide away implementation details and complexity. A large portion of the code you write does not need to be understood perfectly by another class to use it well. For example, if I have a sort(list[int]) -> list[int] function, you only need to understand that if you input a list, it will output a sorted list. Knowing which type of sort it’s using (quicksort, merge sort, bubble sort etc) is usually not necessary.
The benefits of this are:
- If you abstract away complexity, then users cannot rely on the internal details of that complexity. This means you can refactor and make changes in the future, and as long as you keep a consistent interface, you will not be breaking any user code.
- It allows for faster development and less bugs because if a user is not allowed to access any internal components of a system, they cannot introduce bugs/break things within the internal system. By providing them an interface that they have to interact through, you can manage exactly how the system works without their knowledge and also control exactly what they can do with your system.
EncapsulationPermalink
Encapsulation is used to hide away implementation details and complexity. In this way it is very similar to abstraction, but it works at the class level rather system level.
This is easier to explain with an example: Abstraction involves creating interfaces to hide away the complex implementation and interaction between multiple classes. In a real world example, a car hides away its entire implementation and gives a driver access to a basic interface that involves pressing the accelerator, brake, steering etc. You do not need to know how the fuel goes to the engine to drive, or how the locking mechanism of the doors work to lock the doors because you are provided an interface (pedals, keys etc form that interface) that abstracts those details. On the other hand, encapsulation works on a smaller scale. The engine itself is one modular component that can be moved between different cars.
DefinitionPermalink
More generally, encapsulation involves writing classes that are single usable units. This involves using the correct access modifiers for attributes, helper methods, and methods you want other classes to see/use. It also involves hiding away any details that may change the design within a class, such as internal data structures used by the class, so that if you change them in the future then other modules using it will work the same as before.
Comments