- Swift 2 Design Patterns
- Julien Lange
- 775字
- 2021-07-09 21:25:42
The factory method pattern
Our second pattern is a very well-known pattern. It introduces you to the famous concept: "Program to an interface, not an implementation." The instantiation is done in the factory class that depends on the type that we need and the type that needs to be returned to the client.
Roles
The factory method pattern is one of the most used patterns in software designs. The purpose of this pattern is to abstract the creation of an object. The factory method lets a class defer instantiation to subclasses.
You'll see from that time to time that we have mentioned "program to an interface." This is exactly what this pattern does. With Swift, instead of an interface, you'll code with the "protocol" instead of the class itself.
This pattern is used in the following use cases:
- A class only knows about abstract classes or interfaces of objects with whom it has some relationships
- A class wants its subclasses to instantiate the object in order to benefit of polymorphism mechanism
Participants
Participant to this pattern are as follows:
- Product interface: This class contains the definition of our product. We will define what a card is here.
- Abstract product: This abstract class implements the signature of our cards and some methods. You'll see that we keep the prototype pattern that allows us to eventually clone a card. These classes define the properties of our products.
- Concrete product: This class defines our product; in our example, the
Raid Leader
card is a concrete product, such as theFaceless Manipulator
card. - Concrete creator: This class implements our factory method.
Illustration
In our previous pattern, you would have seen the following line:
let raidLeader = Card(name: "Raid Leader", mana: 3, attack: 2, defense: 2)
Here, we directly program an implementation. We need a way to create some cards, but without having the knowledge to know exactly how to construct the card; we can only tell to create the raidLeader
and Faceless Manipulator
cards. At this point of time, the client doesn't want to know that the Raid Leader
card needs three manas, so it provides two points of attack and two points of defense.
Implementation
The implementation of the factory method pattern is as follows:
import UIKit import Foundation //Define what a card is protocol Card { var name: String? {get set} var attack: Int? {get set} var defense: Int? {get set} var mana: Int? {get set} func clone() -> Card func toString() -> String } // AbstractCard // implements the signature and some properties class AbstractCard: NSObject, Card { private var _name: String? private var _mana: Int? private var _attack: Int? private var _defense: Int? init(name: String?, mana: Int?, attack: Int?, defense: Int?) { self._name = name self._attack = attack self._defense = defense self._mana = mana super.init() } override init(){ super.init() } //property name var name: String?{ get{ return _name } set{ _name = newValue } } //property mana var mana: Int? { get{ return _mana } set{ _mana = newValue } } //property attack var attack: Int? { get{ return _attack } set{ _attack = newValue } } //property attack var defense: Int? { get{ return _defense } set{ _defense = newValue } } func clone() -> Card { return AbstractCard(name: self.name, mana: self.mana, attack: self.attack, defense: self.defense) } func toString() -> String{ return ("\(self.name, self.mana, self.attack,self.defense)") } } enum CardType { case FacelessManipulator, RaidLeader } // our Factory Class // Depending what we need, this class return an instance of the // appropriate object. class CardFactory{ class func createCard(cardtype: CardType) -> Card?{ switch cardtype { case .FacelessManipulator: return FacelessManipulatorCard() case .RaidLeader: return RaidLeaderCard() default: return nil } } } //Concrete Card "Raid Leader" //This is the full definition of the Raid Leader Card class RaidLeaderCard: AbstractCard { override init() { super.init() self._mana = 3 self._attack = 2 self._defense = 2 self._name = "Raid Leader" } } //Concrete Card "Faceless Manipulator" //this is the full definition of the FacelessManipulator Card. class FacelessManipulatorCard: AbstractCard { override init() { super.init() self._mana = 5 self._attack = 3 self._defense = 3 self._name = "Faceless Manipulator" } }
Usage
To simulate the use of the factory method pattern by a client, we can write the card creation as follows:
//simulate our client var c = CardFactory.createCard(.FacelessManipulator) c?.toString()
Note
To simulate our client, we simply tell the CardFactory
method that we want a FacelessManipulator
card.
To do this, we use the createCard
method (our factory method), and this method will delegate the instantiation of the card that was asked.
The variable c
has the type Card
and not FacelessManipulator
.
- Mastering Ember.js
- Spring Boot+Spring Cloud+Vue+Element項目實戰:手把手教你開發權限管理系統
- Python王者歸來
- Building Cross-Platform Desktop Applications with Electron
- Nginx實戰:基于Lua語言的配置、開發與架構詳解
- MATLAB for Machine Learning
- Mastering Xamarin.Forms(Second Edition)
- C++寶典
- Microsoft 365 Certified Fundamentals MS-900 Exam Guide
- Spring技術內幕:深入解析Spring架構與設計原理(第2版)
- Delphi開發典型模塊大全(修訂版)
- ABAQUS6.14中文版有限元分析與實例詳解
- 從零開始學UI:概念解析、實戰提高、突破規則
- Python Linux系統管理與自動化運維
- Keil Cx51 V7.0單片機高級語言編程與μVision2應用實踐