swift-design-patterns
Last Update: 19/April/2022.
โญ It will show the creator your appreciation and help others to discover the repo.
If you like the project, please give it a star โ๏ธ About
Software Design Patterns
implemented using Swift Programming Language
. This repository aims to collect as many design patterns as possbile with examples and to serve as a reference material for everyone who is willing to learn something new.
Each design pattern has a complete description and source code. You can view the description by clicking the name of a design pattern and view the code by clicking the [code].
โข๏ธ Disclamer
The motivation behind this porject is to help the others to learn by compiling the knowlege that I have. The material to write down is enourmous, sometimes I may formalize my thoughts in a way that looks strange or unclear. I provide reference materials, so you are able to take a look at the same patterns but from a different perspective or original source.
If you find that something is not clear or has an issue, please, don't judge immediately in a negative way. It's an open source and you have such an opportunity to polietly tell me about that or even create a pool request (which is the best way to contribute). The other piece of motivation is that I really want to create learning material that is solid
and yet easy
to understand for developers that know basics of OOP
and POP
paradigms (since it's Swift
and POP
is almost as important as OOP
IMHO).
I want to keep this repo up to date, implement the latest design, architecture and concurrency patterns. Open-source for eveyone
๐ List of Contents
๐ Common Design Patterns
Behavioral
Behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.
Source: wikipedia.org
Gang of Four
- Chain of Responsibility: command objects are handled or passed on to other objects by logic-containing processing objects
- Command: command objects encapsulate an action and its parameters [code]
- Interpreter: implement a specialized computer language to rapidly solve a specific set of problems
- Iterator: iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation [code]
- Mediator: defines an object that encapsulates how a set of objects interact [code]
- Memento: provides the ability to restore an object to its previous state (rollback) [code]
- Observer: objects register to observe an event that may be raised by another object. The pattern has similarities with
Publish/Subscribe
andMulticast Delegate
patterns [code] - State: allows an object to alter its behavior when its internal state changes [code]
- Strategy: algorithms can be selected on the fly, using composition [code]
- Template Method: describes the program skeleton of a program; algorithms can be selected on the fly, using inheritance
- Visitor: a way to separate an algorithm from an object
Other
- Externalize the Stack: turn a recursive function into an iterative one that uses a stack
- Null Object: designed to act as a default value of an object [code]
- Weak Reference: de-couple an observer from an observable
- Protocol Stack: communications are handled by multiple layers, which form an encapsulation hierarchy
- Scheduled-Task: a task is scheduled to be performed at a particular interval or clock time (used in real-time computing)
- Single-Serving Visitor: optimise the implementation of a visitor that is allocated, used only once, and then deleted
- Specification: recombinable business logic in a boolean fashion
- Publish/Subscribe: messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead categorize published messages into classes without knowledge of which subscribers, if any, there may be. The pattern has similarities with
Observer
,Event Listener
andMulticast Delegate
, however it has its differences and weaknesses as well - Event Listener: NO DESCRIPTION YET (has differences in comparison to Observer and Publish/Subscribe patterns - need to formalize it in a sentence or so)
Creational
Creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or in added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.
Source: wikipedia.org
Gang of Four
- Abstract Factory: a class requests the objects it requires from a factory object instead of creating the objects directly [code]
- Factory Method: centralize creation of an object of a specific type choosing one of several implementations [code]
- Builder: separates the construction of a complex object from its representation so that the same construction process can create different representations [code]
- Prototype: used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects [code]
- Singleton: restrict instantiation of a class to one object [code]
Other
- Dependency Injection: a type accepts the objects it requires from an injector instead of creating the objects directly [code]
- Lazy Initialization: tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed [code]
- Object Pool: avoid expensive acquisition and release of resources by recycling objects that are no longer in use [code]
- Simple Factory: NO DESCRIPTION YET
- Static Factory: used for instantiation of dependent types. Replaces constructors/initializers for object creation that provides additional capabilities such as caching and/or throwing an error
Structural
Structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.
Source: wikipedia.org
Gang of Four
- Adapter: 'adapts' one interface for a class into one that a client expects [code]
- Bridge: decouple an abstraction from its implementation so that the two can vary independently [code]
- Composite: a tree structure of objects where every object has the same interface
- Decorator: allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class
- Facade: create a simplified interface of an existing interface to ease usage for common tasks [code]
- Flyweight: a large quantity of objects share a common properties object to save space
- Proxy: a class functioning as an interface to another thing [code]
Other
- Marker: an empty interface (or protocol) to associate metadata with a class [code]
- Delegate: allows object composition to achieve the same code reuse as inheritance [code]
- Multicast Delegate: advanced version of
Delegate pattern
which allows multiple delegates to be notified about method calls [code] - Coordinator: is an object that encapsulates lifecycle that is spread over a collection of view controllers [code]
- Type Erasure turns an associated type into a generic constraint. Resolves an issue that does not allow to treat a collection of objects that conform to a protocol with an associated type as a collection of regular protocols [code]
- DAO: -
DAO
stands forData Access Object
.DAO
provides abstract interface to a database or other persistence storage mechanism - Adapter Pipeline: use multiple adapters for debugging purposes
- Retrofit Interface: an adapter used as a new interface for multiple classes at the same time
- Aggregate pattern: a version of the Composite pattern with methods for aggregation of children
- Tombstone: an intermediate "lookup" object contains the real location of an object. rise of new classes
- Extensibility: a.k.a.
Framework
- hide complex code behind a simple interface - Pipes and Filters: a chain of processes where the output of each process is the input of the next
- Opaque Pointer: a pointer to an undeclared or private type, to hide implementation details
- Humble Object: extracts the logic into a separate easy-to-test component that is decoupled from its environment
๐
Concurrency Design Patterns
Concurrency patterns are those types of design patterns that deal with the multi-threaded programming paradigm.
Source: wikipedia.org
- Active Object: decouples method execution from method invocation for objects that each reside in their own thread of control
- Balking Pattern: executes an action on an object when the object is in a particular state
- Barrier: is a type of synchronization method. A barrier for a group of threads or processes in the source code means any thread/process must stop at this point and cannot proceed until all other threads/processes reach this barrier
- Binding Pattern: combines multiple observers to force properties in different objects to be synchronized or coordinated in some way
- Double-Checked Locking: used to reduce the overhead of acquiring a lock by first testing the locking criterion (the "lock hint") without actually acquiring the lock. Only if the locking criterion check indicates that locking is required does the actual locking logic proceed
- Guarded Suspension: manages operations that require both a lock to be acquired and a precondition to be satisfied before the operation can be executed
- Monitor Object: is a synchronization construct that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become true
- Nuclear Reaction: is a type of computation which allows threads to either spawn new threads or converge many threads to one
- Reactor: is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs
- Read Write Lock: allows concurrent access for read-only operations, while write operations require exclusive access [code]
- Scheduler: is the method by which work specified by some means is assigned to resources that complete the work
- Thread Pool: maintains multiple threads waiting for tasks to be allocated for concurrent execution by the supervising program
- Thread-Local Storage: is a computer programming method that uses static or global memory local to a thread
๐ Architectural Patterns
Architectural patterns addres issues that arise in software engineering within certain contexts. They are similar to design patterns, but have broader scope of responsibilities. Architectural patterns structure the way how software product/application/platform is built by separating different abstractions into reusable layers. Sometimes architectural patterns are documented as design patterns.
- MVC: is an architectural pattern commonly used for developing user interfaces that divides an application into three interconnected parts. This is done to separate internal representations of information from the ways information is presented to and accepted from the user. The
MVC
design pattern decouples these major components allowing for efficient code reuse and parallel development [1] - MVP: is a derivation of the modelโviewโcontroller (
MVC
) architectural pattern, and is used mostly for building user interfaces. InMVP
, the presenter assumes the functionality of the "middle-man". InMVP
, all presentation logic is pushed to the presenter [1] - MVVM: is a software architectural pattern that facilitates a separation of development of the graphical user interface โ be it via a markup language or
GUI
code โ from development of the business logic or back-end logic (the data model). The view model ofMVVM
is a value converter, meaning the view model is responsible for exposing (converting) the data objects from the model in such a way that objects are easily managed and presented [1] - MVVM-C: basically the same
MVVM
arcitectural pattern, but with an addition ofRouting
layer, which isCoordinator
pattern - VIPER:
VIPER
is an application ofClean Architecture
toiOS
apps. The wordVIPER
is a backronym forView
,Interactor
,Presenter
,Entity
, andRouting
.Clean Architecture
divides an appโs logical structure into distinct layers of responsibility. This makes it easier to isolate dependencies (e.g. your database) and to test the interactions at the boundaries between layers [8] - RIBs: is the cross-platform architecture framework developed by Uber. RIBs means: Router, Interactor and Builder, which are core components of this architecture. The key aspects of the architecure are: modible apps with large number of engineers and nested states [10]
- Clean-Swift: is a derivarive architecture of the
Clean Archtiecure
proposed by Uncle Bob
๐ฆ Swift Patterns
In
Swift
, there are two basic kinds of patterns: those that successfully match any kind of value, and those that may fail to match a specified value at runtime.The first kind of pattern is used for destructuring values in simple variable, constant, and optional bindings. These include wildcard patterns, identifier patterns, and any value binding or tuple patterns containing them. You can specify a type annotation for these patterns to constrain them to match only values of a certain type.
The second kind of pattern is used for full pattern matching, where the values youโre trying to match against may not be there at runtime. These include enumeration case patterns, optional patterns, expression patterns, and type-casting patterns. You use these patterns in a case label of a switch statement, a catch clause of a do statement, or in the case condition of an if, while, guard, or for-in statement.
Source:
swift.org
The following patterns are not part of the design patterns
topic. However, the presented language patterns
are related to the design patterns
theme, since they offer reusable solutions for common design scenarious when using the programming language. IMHO
they are essential to master in order to realise that patterns are everywhere - language, constructions, architectures, approaches etc.
- Wildcard: a wildcard pattern matches and ignores any value and consists of an underscore (_). Use a wildcard pattern when you donโt care about the values being matched against [code]
- Identifier: an identifier pattern matches any value and binds the matched value to a variable or constant name [code]
- Value-Binding: a value-binding pattern binds matched values to variable or constant names. Value-binding patterns that bind a matched value to the name of a constant begin with the let keyword; those that bind to the name of variable begin with the var keyword
- Tuple Pattern: a tuple pattern is a comma-separated list of zero or more patterns, enclosed in parentheses. Tuple patterns match values of corresponding tuple types
- Enumeration Case: an enumeration case pattern matches a case of an existing enumeration type. Enumeration case patterns appear in switch statement case labels and in the case conditions of
if
,while
,guard
, andfor-in
statements - Optional: an optional pattern matches values wrapped in a
some(Wrapped)
case of anOptional<Wrapped>
enumeration. Optional patterns consist of an identifier pattern followed immediately by a question mark and appear in the same places as enumeration case patterns - Type-Casting: there are two type-casting patterns, the is pattern and the as pattern. The is pattern appears only in switch statement case labels
- Expression: an expression pattern represents the value of an expression. Expression patterns appear only in
switch
statementcase
labels
๐ References
There were used a number of reference materials such as:
- Wikipedia
- swift.org
- Apple Developer Portal
- Design Patterns: Elements of Reusable Object-Oriented Software
- SOLID
- Swift Patterns
- Coordinator Pattern
- VIPER Architecture
- Code Complete. Wikipedia
- RIBs. GitHub
๐โโ๏ธ ๐โโ๏ธ Contributing
You are very welcome to contribute to this project! There are a few rules that need to be followed:
- If you want to implement an example code for an existing
Design Pattern
then you need to wrap it up in.playground
file. That makes code compilation is a matter of launching a file and not worrying about managing a giganticXcode
project. - If you want to write about a
Design Pattern
that is in the list, but has not been implemented yet, then you need to follow the following style guide:- Write the description of a design pattern
- Split the example code into subsections
- Write explanation for each snippet of code
- Don't make your example complicated and too many details
- Write conclusion where you highlight the pattern
- If you want to write about a
Design Pattern
that is not in the list, then please use the aforementioned rules + write a short description and specify the category of a pattern. - If you find that some important detail is missing in an existing
Design Pattern
then, please politely write it down. The more details and arguments you use, the more easier it will be to address the issues.
๐จโ๐ป Author
๐ Licence
The project is availabe under MIT licence.