Creational design patterns provide a method to abstract the instantiation logic
of objects, promoting flexibility in object creation rather than using direct
instantiation with the new operator. This makes the program more flexible when
determining which objects need to be created for a given instance.
The Singleton Pattern is one of the simplest and most well-known design patterns in Java. It falls under the category of creational patterns and ensures that a class has only one instance, while providing a global point of access to that instance.
-
Lazy Singleton Pattern:
- Implement the Singleton pattern using lazy initialization. The instance should be created only when it is first requested, optimizing memory usage.
-
Double-checked locking:
- Declare the instance variable as
volatileto ensure visibility across threads. - Modify the
getInstancemethod to implement double-checked locking, ensure that the instance is only synchronized during the initial request, improving performance by avoiding synchronization overhead in subsequent calls.
- Declare the instance variable as
The Factory Pattern is one of the most commonly used design patterns in Java. It provides an approach to object creation that separates the creation process from the use of the objects.
In the context of language localization, formats like en-US for American
English or en-GB for British English are common. We can implement a language
loader that loads either the American English or British English instance based
on the input.
-
Factory and product:
-
Implement the abstract product
ILanguageinterface with classes likeAmericanEnglishandBritishEnglishas concrete product. -
Implement a concrete factory inherit
ILanguageFamilyinterface to generate Language objects using country codes likeUSorGB.
-
-
Factory and abstract factory:
- Leverage the abstract factory
ILanguageFamilyFactoryto select languages based on language codes likeenorfr. - Implement a provider to streamline and enhance the object creation process.
- Leverage the abstract factory
The Builder pattern is a creational design pattern that facilitates the separation of the construction process of a complex object from its final representation.
This pattern is particularly beneficial when dealing with modules have tightly
coupled attributes or when simplifying JNI interactions. To illustrate this
further, assume IShader as an external API call, while IMaterial require a
fully constructed shader with initialized content. The IMaterialBuilder
simplifies the process by managing both the I/O loading and initial binding
within the builder.
-
Create a mock implementation that inherits from IShader for simulation purposes.
-
Implement the products
IMaterialinterface and the BuilderIMaterialBuilder.
The Prototype Pattern is a creational design pattern that optimizes object creation by enabling objects to be cloned instead of created from scratch. It is particularly useful when direct object creation is expensive. It provides an efficient way to generate multiple instances of an object by cloning a prototype.
For example, loading mesh or texture resources often involves expensive I/O operations. To enhance performance, these resources can be preloaded into a cache. Minor modifications, such as generating runtime UUIDs or adjusting positions, can then be applied without the need for reloading.
-
Implement
MeshResourceandTextureResourcebased onIResourceinterface. -
Develop a standard resource creator based on
IStandardResourceabstract and preload all standard resources in theloadStandardResourcefunction with unique id.
Structural design patterns focus on the composition and relationships between objects and aim to solve how to build flexible and reusable structures of classes and objects.
The Adapter Pattern serves as a bridge between two incompatible interfaces and is categorized as a structural design pattern. It achieves this by transforming the interface of a given class into another interface that the client expects, thereby enabling classes that would otherwise be unable to cooperate to function together seamlessly.
The goal of the task is to design a system that supports both a JDK-based compressor and an external compressor. The adapter should provide a unified interface, abstracting away the differences between the compression implementations, while ensuring ease of integration and the capability to load multiple sub-adapters dynamically.
The Composite Pattern is used to treat a group of similar objects as a single object. The Composite Pattern organizes objects in a tree structure to represent both the part-whole hierarchy. This type of design pattern belongs to the structural patterns category, as it creates a tree structure of object groups.
In this guide, we will illustrate the Composite Pattern using a 2D rendering system as an example. We'll represent individual shapes, like circles, as well as complex compositions, or scenes, made up of multiple shapes. By leveraging Signed Distance Functions (SDFs), we can define the shapes mathematically and combine them into more intricate structures, such as multi-shape scenes.
-
Implement specific shapes such as circle based on
IShapeinterface. The SDF for a circle calculates the signed distance from a point (x, y) to the circle's edge using the following formula:$\text{SDF}(x, y) = \sqrt{(x - \text{centerX})^2 + (y - \text{centerY})^2} - r$ -
Create a Scene that represents a composite of shapes. When calculating the SDF for the scene, it loops through each shape and determines the minimum distance from the point to all the shapes.
More information: https://www.shadertoy.com/view/3ltSW2
Behavioral design patterns focus on communication and interaction between objects and aim to solve the distribution of responsibilities and the encapsulation of algorithms between objects.
The Chain of Responsibility Pattern creates a chain of receiver objects for a request. This pattern decouples the sender and receiver of the request based on the type of the request. It is classified as a behavioral design pattern.
The Command Pattern is a data-driven design pattern categorized under behavioral patterns. It primarily addresses the challenge of tight coupling between the requestor and the executor within software systems, particularly in scenarios that require behavior to be recorded, undone/redone, or managed through transactional processing.
The Interpreter Pattern provides a mechanism for evaluating a language's grammar or expressions and is classified as a behavioral design pattern. It is used to construct an interpreter capable of analyzing and processing sentences based on a specific language or grammar.