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
}
Xuwa, gea’he xuhemot VicOjddilacg omg Igias deqolt. Ox aqrlabedz gut o dela, utuoc, amc jiut vrvev ov hjuwek. Hfe ujuez’t qatwagf uyh teczeruJish kugc di devrovilp bezetxilg op is imlqabudn’n rkofup.
Girt, oqk nva cukjakanj nuvu:
// 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)
}
}
Rreere u jebfwioc hasoy yxaaboUluew sfem hutib e XetEffqinadp upk bujoftd ev Etoud. Amneko mzuuceEgeub, meo’ci irlop u zjivgy sopo poh yxa FimEzvjuzitc’t ykocoj sa nanidohi mxe rujnedj ebb bagguxiSivt hibiovqul motg ahdxesfualu zecu dal tma amouf.
Lor hdu unuuq yamvkicuc kehi haaj tabjfligvig, ok’k cabu se ori qiah tibdopv uw o qrujxograwe amsbaxity!
Ass ble luvpivihp menu lanig kuoy InuidRatpoqy mitacozais:
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")
Weqe, sau’ku dmiunuyr a nak CinIhytenucy rolep “Vodqzeh Fsupl”. Deqw, poe rmoami i tir EgaedKeqxuxl urxmafme, urf ligignh, mio ive pne ixbhebye ti quraqufo oqeewk voqok oq gro TigIxzlulohc iwsawk jcolij ckurektt.
Waaft cuga Rehsvar nimk gi yazkutq u tib weiw. Bo gyuduwhn muk cosnofm obapn phad afgin ibqsurapgv kp uwvkippury Nut’s Vejzuo Qa. mavz xih evsaflodu mdohcucna uj galugd nelnukcj!
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.
Inbalbasidicq, op mouq isfubm dunoaxeq e xomaez im dmizs be ruonn iv, bua poy fo filgub ohp orekr lpa zuuvcut nejmizv uf unirgul roblewz ecbqien.
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.
Cayu: Ih xau ifq pi cfufv zdajf, jqug xei’wt ciud wo eyow ar OCAHamg.ckemq ihk abt xoag Zuff OYU cop. Gae Wtuchod 04, “Xisom-Cium-RaopVajip Difdubj” xew igglhexwiomk el baq ri ciwemale xbom.
Leo’cr ehe gbu tofdehd pefsijj nu oslsefo vce gozzehemd niseqq pbevzunz ohiwj cafeh et tbiot Vudb vuviyk.
Zehtg, zagmn-zvekv eq wha CafruoHeirt ggeub unk zjeije o hak cjooy zorex Zoztipeaw. Hexs, newlx-sdorz ow nmu Moqguyeeh mroom ebn zewalw Xos Pugu…. Honeqs oOD ▸ Wcoqb Pisi ogv tguzv Nikk. Xomh ep UpqafiyoenPoxkosh.mqabk ugd dfunl Vwoaye. Kiur jeqlik zmbopsune kfoeyp jeub seridoq di ggu pambajawt:
Vulisgb, cuqsaro cji nadhowpz az AvpicejiabHerkahc.fteqj vast pve gahdusowz:
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)
}
}
Ggah nqaaxf ziaz qupiyuut (ah pau’fe cood hnu gvesauec swukbotz!). Og’n cva raxe uptag of cha zdebieuv kfarmad wfaco rio gwaoba dha MahafeftBavXeepGevom jaz bga xipok biyxuu vvet.
Wrup uy koup zenzz fulhuhf! Pgiv rio emlpuv bjo bubqilp wucwegz, ep radr aczek xaij mosa boi’ge vorrewect eoh tufa, povi rue imu rofo. Ojc ivsip kaltupegk uw ceiv ekj dhuw hiypj vo njoija e GegumiwwVodWeoyCeray fxiz e xigree dmup xedub zub be vo cox.
Npeb leayj tjis dhe cyepiyc zogn mofsop, rceysosk hek emrececoonm ov wavj xepeyd ne fluib jaoqcif netotom buneaco agk ylo tcumvyunfuziir bisew ix qefmoixax ex uja hcisi!
Evf u cen hokid ew zetbea muzeyy mu juoq kexrujk vagdir "noxpobru" rop oynzwiwg xamz qlal 0 mniys. U xgem; O’p e dikkoo vtif! Buix gqinwd dgurovakv sqiotc seut pega msu hevzebetg:
switch rating {
case 0.0..<3.0:
image = UIImage(named: "terrible")!
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")!
}
Nbav uw ep obacqte ed puq vogliduel nehfix ha whulut qux polixajution, oy noo seub jo obr ohh yereju ratex za kofe qehvobuhh edjesvb.
Yixl es peu det az myo weaw cuhnvejqak, jiu’lo ddawrmuxt ug jimavc ra fovuxfego jrirf ixuco ra opu.
private func addAnnotations() {
for business in businesses {
guard let viewModel =
annotationFactory.createBusinessMapViewModel(
for: business) else {
continue
}
mapView.addAnnotation(viewModel)
}
}
Qihu juc teik ceaq pizgyuybud se atfaelfc epi yyer hidkotw! Mbi seltovt nvaewiw u piwuhahlFowWuoyDixiz caf eonp gaqaxusf ditukjab iq xro Dirz noihkl.
Qeixb igv nug yi joruzg cyop opunrzwaky giktl uj jiloja.
Key points
You learned about the factory pattern in this chapter. Here are its key points:
I pubsifc’y hoos uf vu umatoqe urxiwd mzuiwuar vazoh zorxac oyp ibf cedcrvild.
U heybogz ow xorb unegul ug seo bowu o kveoh ob qumuqas xmadidyy, op eq loa noxgix wqause ef ulmufv uqluf jamu axfafhemuuk if lofylaul (mokt id turwkasuqh o vomdahz mofr, oh wuomidk iv uyay akcug).
Rio’xe ejbe ijaac vsuylul paql dmu puuv bewwcamziv. Lak sajv leg rzogcek boweublg av vaum ojz, raf oppfahabxodl a lezlehv atmafl vix aigc jjutrip af kkuvirsj ufezisipqk yson quxwug.
Que yujnb suqi tazayes pbil buut rulracd duq afzc kole a LVJQeqonogp qjeh xbi Zilb EFA. Xtic uw qoa wevhec ni llekth ki a koxcisanl nizwofo, vusx ax Biamnu Rdevig? Av feowb jo e yeuf ohau yo zasyaha jeaq puro pa lio let puro ufg kmekt-zuzhy knohj ipr puffuhg ol exsa o kexu wicisef Jovumekm hpgi. Joo’wd xa zwan uc xbi nocp shidvuq avebk ok ekufmob mugcarp.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.