Dart OOP Design Patterns
Object-Oriented Design Patterns in Dart
Object-Oriented Design Patterns are general, reusable solutions to common problems in software design. These patterns help to solve design problems by providing established and well-tested templates for building software components. Some common OOP design patterns are:
- Creational Patterns – Deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.
- Structural Patterns – Concern how classes and objects are composed to form larger structures.
- Behavioral Patterns – Focus on communication between objects, what is the best way to interact between objects in a system.
In this explanation, we'll cover a few commonly used design patterns in Dart with examples.
1. Singleton Pattern (Creational)
The Singleton Pattern ensures that a class has only one instance, and provides a global point of access to it.
Example: Singleton Pattern in Dart
Output:
Explanation:
- The
Singleton
class has a private constructor_privateConstructor
, which prevents external instantiation. - The
factory
constructor returns the same instance (_instance
) every time it’s called, ensuring only one object exists.
2. Factory Pattern (Creational)
The Factory Pattern defines an interface for creating an object, but it’s up to the subclass to decide which class to instantiate. It helps when the exact type of the object isn’t known until runtime.
Example: Factory Pattern in Dart
Output:
Explanation:
AnimalFactory.getAnimal
decides whichAnimal
subclass to instantiate based on the provided type.- This pattern hides the instantiation logic from the client and centralizes it in the factory.
3. Observer Pattern (Behavioral)
The Observer Pattern is used when an object (subject) needs to notify other objects (observers) about changes in its state without knowing who or what those observers are.
Example: Observer Pattern in Dart
Output:
Explanation:
- The
Subject
maintains a list of observers and notifies them whenever the state changes. - The
ConcreteObserver
implements theObserver
interface to respond to updates.
4. Strategy Pattern (Behavioral)
The Strategy Pattern is used to define a family of algorithms, encapsulate each one, and make them interchangeable. The Strategy
allows the algorithm to vary independently from the clients that use it.
Example: Strategy Pattern in Dart
Output:
Explanation:
- The
SortStrategy
interface defines a sorting method, while the concrete strategies (QuickSort
,MergeSort
) implement it. - The
SortContext
class uses theSortStrategy
to execute the appropriate sorting algorithm. - This pattern allows switching between sorting algorithms at runtime.
5. Decorator Pattern (Structural)
The Decorator Pattern allows you to add behavior to an object dynamically without altering its structure. It is useful when you want to add responsibilities to objects without affecting other objects.
Example: Decorator Pattern in Dart
Output:
Explanation:
- The
SimpleCoffee
class is the base class, andMilkDecorator
andSugarDecorator
are decorators that modify the behavior of thecost()
method. - The decorators add additional functionality to the
SimpleCoffee
object dynamically, without modifying the original class.
Conclusion
Design patterns provide proven solutions to common software design problems. In Dart, object-oriented design patterns like Singleton, Factory, Observer, Strategy, and Decorator help in organizing code for maintainability, flexibility, and scalability. These patterns allow you to build more robust and scalable applications by following best practices that are easy to implement and extend.