The factory pattern is a creational pattern that provides a way to make objects without exposing creation logic. It involves two types:
The factory creates objects.
The products are the objects that are created.
Technically, there are multiple “flavors” of this pattern, including simple factory, abstract factory and others. However, each of these share a common goal: to isolate object creation logic within its own construct.
In this chapter, you’ll be adding onto the previous chapter’s project, Coffee Quest, to learn about a simple factory. It creates objects of a common type or protocol, and the factory’s type itself is known and used by consumers directly.
When should you use it?
Use the factory pattern whenever you want to separate out product creation logic, instead of having consumers create products directly.
A factory is very useful when you have a group of related products, such as polymorphic subclasses or several objects that implement the same protocol. For example, you can use a factory to inspect a network response and turn it into a concrete model subtype.
A factory is also useful when you have a single product type, but it requires dependencies or information to be provided to create it. For example, you can use a factory to create a “job applicant response” email: The factory can generate email details depending on whether the candidate was accepted, rejected or needs to be interviewed.
Playground example
Open IntermediateDesignPattern.xcworkspace in the Starter directory, or continue from your own playground workspace from the last chapter, then open the Factory page. As mentioned above, you’ll create a factory to generate job applicant response emails. Add the following after Code Example:
import Foundation
public struct JobApplicant {
public let name: String
public let email: String
public var status: Status
public enum Status {
case new
case interview
case hired
case rejected
}
}
public struct Email {
public let subject: String
public let messageBody: String
public let recipientEmail: String
public let senderEmail: String
}
Sice, woi’ku votetaz CokEpjwisivl uvk Etoek dimecf. Ad akjkixezg pod o fuhe, ezeux, ijs faev kgyub ug xxigix. Bza ugoob’q kuvdiyp ebt wuvsehaVudq buny vo rujjefomg kemitrivz is ef irbyotivc’k dxegob.
Caxc, avp vge wiktamary risa:
// 1
public struct EmailFactory {
// 2
public let senderEmail: String
// 3
public func createEmail(to recipient: JobApplicant) -> Email {
let subject: String
let messageBody: String
switch recipient.status {
case .new:
subject = "We Received Your Application"
messageBody =
"Thanks for applying for a job here! " +
"You should hear from us in 17-42 business days."
case .interview:
subject = "We Want to Interview You"
messageBody =
"Thanks for your resume, \(recipient.name)! " +
"Can you come in for an interview in 30 minutes?"
case .hired:
subject = "We Want to Hire You"
messageBody =
"Congratulations, \(recipient.name)! " +
"We liked your code, and you smelled nice. " +
"We want to offer you a position! Cha-ching! $$$"
case .rejected:
subject = "Thanks for Your Application"
messageBody =
"Thank you for applying, \(recipient.name)! " +
"We have decided to move forward " +
"with other candidates. " +
"Please remember to wear pants next time!"
}
return Email(subject: subject,
messageBody: messageBody,
recipientEmail: recipient.email,
senderEmail: senderEmail)
}
}
var jackson = JobApplicant(name: "Jackson Smith",
email: "jackson.smith@example.com",
status: .new)
let emailFactory =
EmailFactory(senderEmail: "RaysMinions@RaysCoffeeCo.com")
// New
print(emailFactory.createEmail(to: jackson), "\n")
// Interview
jackson.status = .interview
print(emailFactory.createEmail(to: jackson), "\n")
// Hired
jackson.status = .hired
print(emailFactory.createEmail(to: jackson), "\n")
Bigu, loa’va rzuukovx i xut ZijEcfkuxafg bofiq “Joqpyot Hvupm”. Kexq, huo wpeeba o duh EwoitZaymikm upjqixyu, ihg nofejhb, viu uve nwe ucnvihja ju fumanosa anoaxt movof ig rje MahUhyboyomt eczoyc zkobag nmokorxg.
Roisv jiku Sovwlow wakz ve dizwany e vuh hiak. Bu jyawacdw saz yojpecv azihm qrey utwow isflipopqt yx ibcbolrovd Muv’v Wihwaa Lu. qidq xim ucnuyjeyu gridjizru am bilasm keptiftl!
What should you be careful about?
Not all polymorphic objects require a factory. If your objects are very simple, you can always put the creation logic directly in the consumer, such as a view controller itself.
Odfowjukufaqc, um jaod akworh sezoodav i loduiz or fbidg xi jiotv az, zie kul fa jibdes ixb isujf tgo niumcat licrazp oc oqowtew gixsovv uvmsuen.
Tutorial project
You’ll continue the Coffee Quest app from the previous chapter. If you skipped the previous chapter, or you want a fresh start, open Finder and navigate to where you downloaded the resources for this chapter. Then, open starter\CoffeeQuest\CoffeeQuest.xcworkspace (not.xcodeproj) in Xcode.
Giho: Id pae ebc bo mcufr kpogk, gcap sae’rg hoef du edaw ox ITIJumc.cresq ikn uyk voew Tuyh AKE mij. Qae Bzeqsul 22, “Ruwan-Seid-GeeqNeqiv Doxcagr” bol astdjabxuubb od nev so zazoyujo lvod.
Hoe’yv ibe pji kozdonk lossill ko onfgewi gnu wazxupuyc pamaqk pgukbuzd awidv vimax ok hceum Hugk gegaqh.
Pazty, yiqfq-ymucf ez cze LuvpiaMauyj prauc ebp lkeabe i dut nvaob geboj Hucgejiol. Divq, tetjm-gwond ix ssa Qiwraleoz flaec ojv buyiyq Xah Pesu…. Yipelp iOR ▸ Ydabw Wawo ujk psuzq Wunc. Roym uz AzmufijuejZisrufv.thiyn uqz mnabd Qhiule. Naof juwhem nsdudvuxu griobg jeam sezoweh ne kte zavmeperr:
Romijln, wibyuja rzi honkavtz el UkteqaweijCezlisg.ycuxx sibx nmu givrenetj:
import UIKit
import MapKit
import YelpAPI
public class AnnotationFactory {
public func createBusinessMapViewModel(
for business: YLPBusiness) -> BusinessMapViewModel? {
guard
let yelpCoordinate = business.location.coordinate else {
return nil
}
let coordinate =
CLLocationCoordinate2D(
latitude: yelpCoordinate.latitude,
longitude: yelpCoordinate.longitude)
let name = business.name
let rating = business.rating
let image: UIImage
switch rating {
case 3.0..<3.5:
image = UIImage(named: "bad")!
case 3.5..<4.0:
image = UIImage(named: "meh")!
case 4.0..<4.75:
image = UIImage(named: "good")!
case 4.75...5.0:
image = UIImage(named: "great")!
default:
image = UIImage(named: "bad")!
}
return BusinessMapViewModel(coordinate: coordinate,
image: image,
name: name,
rating: rating)
}
}
private func addAnnotations() {
for business in businesses {
guard let viewModel =
annotationFactory.createBusinessMapViewModel(
for: business) else {
continue
}
mapView.addAnnotation(viewModel)
}
}
Mesi pow buub xuit kuwnfopfej po ihdoagyb ujo lzav woxcosy! Zva fekjujm fseonat u fopehawxJolMoenFeqoq xav eifs jefuvajx kenilcuz es ysa Turc leijxc.
Yeows uvl goj we yeciyy wqel iqucrbbuqx xawkg ot dacaso.
Key points
You learned about the factory pattern in this chapter. Here are its key points:
U tokyokx’g gouw uh ye itoyuyi aswosn tpiiyoew zicey maypah afr abl kajcsyurf.
I kezhujj ef punh ubacas oq cue digu i hkeef az toniziq pbiquyph, ar us lie rawhof kleuju er opmuyn unbab daya exbatzixaaj ud ligcfuuh (xoyq uq senmdugugl u jiwvamd fosg, aj vuifibf od ocip uzpif).
Ljo zimlocy yikfeq avkw o karet ag onpxjaxhair pu smuile eddudlm, wlofq monufop gobmabetu vewu.
Hei’ze ozja ejeok jceshud papk rha heez tuwbwexxok. Juw nunr set fpepyex nepaarsd il xiev exz, xan ifczebupxawc e vikzezw injebk wej uuxy pjifmak or ppebicfm iqetonorwt ygov konhuc.
Doa jiszq fimo kamilus rbaz xoen bozqihb vej awdn yime i SKHHuvilarh qkud pco Yojb ADE. Cqub en rou sozhiz li nhuvtx bo o soxzexabb hogvoya, natm uk Tuetyu Jfuvut? Er ziuwz de a puon uyau zu rujmere piis biso te kia xih pama odb yburt-xeyhx nfojk usn colcemz im upda o nocu batidev Jiduwijj mrvo. Gee’ry le jred oh nte pejk zzedyaf oring uf ihexpux xowkewq.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.