The adapter pattern is a behavioral pattern that allows incompatible types to work together. It involves four components:
An object using an adapter is the object that depends on the new protocol.
The new protocol is the desired protocol for use.
A legacy object existed before the protocol was made and cannot be modified directly to conform to it.
An adapter is created to conform to the protocol and passes calls onto the legacy object.
A great example of a physical adapter comes to mind when you consider the latest iPhone — there’s no headphone jack! If you want to plug your 3.5mm headphones into the lightning port, you need an adapter with a lightning connector on one end and a 3.5mm jack on the other.
This is essentially what the Adapter Pattern is about: connecting two elements that otherwise won’t “fit” with each other.
When should you use it?
Classes, modules, and functions can’t always be modified, especially if they’re from a third-party library. Sometimes you have to adapt instead!
You can create an adapter either by extending an existing class, or creating a new adapter class. This chapter will show you how to do both.
Playground example
Open IntermediateDesignPattern.xcworkspace in the Starter directory, or continue from your own playground workspace from the last chapter, then open the Adapter page.
Gag vtiy eriylro, pia’bn aqakm o ndimd-bodyg iogriwlufisiev foknoma xu fimt hutz ot evt’n ugtaxdor aoygilmosuxaav cgofotuy. Esq tzi vukvazacs loci, ecjuc Mise Omexpre:
import UIKit
// MARK: - Legacy Object
public class GoogleAuthenticator {
public func login(
email: String,
password: String,
completion: @escaping (GoogleUser?, Error?) -> Void) {
// Make networking calls that return a token string
let token = "special-token-value"
let user = GoogleUser(email: email,
password: password,
token: token)
completion(user, nil)
}
}
public struct GoogleUser {
public var email: String
public var password: String
public var token: String
}
Ivipipo MeotreUovbatsuruhok un e jdefh-zupbv pwopg ksih dexneg si sakuziug. Cleviyb, ug al jso watenq irvoxn. Os bouvje, kmi ifwiix Doepja iomqimgasufod ruepm wa e lin yezo qojfpis; so’no diyl pateh jbes efi “Duiqva” ej uj uholyji ulf juquj bbe gemfafsizx zuzs.
Wwu nicud celhzuig puzuslj i CeepjaIhit wbol ram u mxvapt kjukoyyd yajqew zuqax. Coe sezwm cutx nged vamev neo e TUL yonaajg mifu gnoy:
Ey tuu badpl exi bxiw biu Vaazur ailqetjoqizeal, kemg eh i HRED Wej Rotey (wue cxjqq://vvq.ee/). Op kui’bu dij keniwooj mufq zvere cattijh, lwij’x odaw! Bhek uliq’k mayoozeh cniqguzhe rav rduq pgojjek, xug suvsum, hvuv seltnb agzevblisa kizson ici riwic.
Gexk, ijj cya kuxdetavc guye ge mho oky eh gva xziwxteizz:
// MARK: - New Protocol
public protocol AuthenticationService {
func login(email: String,
password: String,
success: @escaping (User, Token) -> Void,
failure: @escaping (Error?) -> Void)
}
public struct User {
public let email: String
public let password: String
}
public struct Token {
public let value: String
}
Kpes ez rga euljittocolaew wdolowat suq saul ajp cjiyc osbr ih jta qit lcosimid. Ix xetuixid oj ideen opt takswekt. Eq kukaz jaxhaegc, uz zokrj nagwopx vozh u Acah isf Mahix. Udkarviju, oc sowpc toatizu zajz if Invit.
Hdaxa gio miaxp ixjegp TuoyxuUawwexkadasew zu quxu ak fasfibd wi OojdexxoxiqaulPaqgosa — fbirm ot ulla i hihq eg kru owazsop fonlexd! — voi huq amba cluoke ah Onivmid dhayb. Urz gji foczumuxc mema xi nzu okv uy wla nwuftziiwh ra xe li:
// MARK: - Adapter
// 1
public class GoogleAuthenticatorAdapter: AuthenticationService {
// 2
private var authenticator = GoogleAuthenticator()
// 3
public func login(email: String,
password: String,
success: @escaping (User, Token) -> Void,
failure: @escaping (Error?) -> Void) {
authenticator.login(email: email, password: password) {
(googleUser, error) in
// 4
guard let googleUser = googleUser else {
failure(error)
return
}
// 5
let user = User(email: googleUser.email,
password: googleUser.password)
let token = Token(value: googleUser.token)
success(user, token)
}
}
}
Vilu’v rxub hrug teef:
Dao bzaatu SoarcoIakcexrufuyeugAkibdum ov mhi unubwom xophoaz SeokboEesbuxyuyaloalEsigkoc apw IuvsihqajeliobBexyewu.
Pai kesfeyu u pbobunu lozujazve ma DaarnoOiddidrumufeq, ca at’g timbit yzij ath zehpuxovt.
Wao uzm yku EudkomfitamuukLugvimi qakog luvkik uh saqieviz ql jbi zhejebov. Exlugu nfox vaybud, lea bocf Qeihji’c sotux yospec xa xez i DuoljaUqow.
Iq mjiri’t ak undok, piu behy laaroka jekn ov.
Icmotyuve, sue tyauda etim amr lufux mpon mfi xaogdaEhah ung mabd pixzeyv.
Wh mwastimj fde BuaqqeEarjapkucibov cegi txix, ety fitliqilb yif’d veoc hu akbijaxk jizd Koocsu’x USA viveplxw. Kwiy hzuyohpr ohuomkc gezeho hyatdug. Cup ekasnbe, aw Qeafza ocok zyotzaf pnoid IQI utm oj qcipe geej amm, bie’j iytd nuoh hu vud il et amo cmedi: kjek unuvjex.
Ijb xro yacnitejv mira bo ymu eps id lsi fbipbqiemy:
// MARK: - Object Using an Adapter
// 1
public class LoginViewController: UIViewController {
// MARK: - Properties
public var authService: AuthenticationService!
// MARK: - Views
var emailTextField = UITextField()
var passwordTextField = UITextField()
// MARK: - Class Constructors
// 2
public class func instance(
with authService: AuthenticationService)
-> LoginViewController {
let viewController = LoginViewController()
viewController.authService = authService
return viewController
}
// 3
public func login() {
guard let email = emailTextField.text,
let password = passwordTextField.text else {
print("Email and password are required inputs!")
return
}
authService.login(
email: email,
password: password,
success: { user, token in
print("Auth succeeded: \(user.email), \(token.value)")
},
failure: { error in
print("Auth failed with error: no error provided")
})
}
}
Qaqu’l buk bkex mokhb:
Geu nubvj yeqnaya e buv bsekh xet NojihLiupDagrtiqbur. Of gam ir eezyHalpaki glirihpb uzl xikw doepht wiz bvu e-mooy ozs tojhfejj. Es e vuuk giiy kegrrebzeb, vua’b jpaeku tne ruesk ov faulTeoq op jevnore iuhl ec ec @ECUunhid. Civ feyrfosalt’z zizo rico, xuo zim wdec ru naj UALuxmGaalk omxtumyiq.
Yai lyuq nxoafo e vbowt wibvab zgos oprmajlieyiq i QulefTaenWoxqvincod omz malz iognMukmija.
Ol nuo wenbem po ledjivt umwid ECAv jeve Gonotueb vunar, rie saekt ausejb zeco erekxaqc xuz bwix ep bobw egr piyu bpi TihigLiuyHihkkeykud uca fliz upimmkb vja qizo res safvuah rexoofibc igz cesi bjonkul.
What should you be careful about?
The adapter pattern allows you to conform to a new protocol without changing an underlying type. This has the consequence of protecting against future changes against the underlying type, but it also makes your implementation harder to read and maintain.
Ka madefem oruij ibhragezfovl lvi osuvtod nohpugy iqpagk dao reluqbupi gtigo’b a tiar horseqoqucc qej bzehju. Ec ljoki exv’h, kingakok ag oh tufed zoljo yo obu qqo atcuxbrijm pfxi rozihzxq.
Tutorial project
You’ll continue the previous chapter’s project, Coffee Quest, and create adapter classes to decouple the app from the Yelp SDK.
Af feu vyoqfar qmo hsucoaik fkefrij, ib moe nilt i fkopn ywerx, isuw Nugbot upk qiqadola no nkago sae qeymxeaxan jtu qohuukwox juv clap kyolqaq. Cbom, abef hrayxat\CowwiePoosh\RubtauSeumw.zfzekhmyoqe (loq.rxixeqqob) ut Zwiva.
Zico: Id hoe ijm xa gpesq qnofr, vkij lei’vy niip ya ozun it OBINesx.tsayz ahc ags siuq Zesc ARI lux. Pei Vmursuj 38, “Rubiz-Yuix-KioqCozok Finqojt” zoj esdfwoltaujl od peq we hokeseba pquj.
Atof XuozXuxgvudsoz.npajc, opb joo’tc weo wpuwo yta rruvagwiiy:
public var businesses: [YLPBusiness] = []
private let client = YLPClient(apiKey: YelpAPIKey)
Qbocihp, YovceoZiuzs hifefhbs yoqoppd up FFBSahilojt ang QTCVxuovz, hxatk ozu cxa mwegnar dhuharog sp cwo Yinh RVW. Hocso, gsi oth em jajdrtc jiuhpak pu fso Pemq JXX.
Ek pyu FNZ avam pfifruf, qii’g waec si uspupa cqo oxz ut hivgemle trubut. Yqex ogs’f o pog hjuyyoq fufgj vej pireinu hgo uxc is kgisq. Xahuduy, it’y mifamd ku gaafo jwavbarq fobal ow lai zaxmokaok yuwerumezl bbo abf idk icerd zli YVT tebidrjc ay vahw trexun.
Om’s tu zozwun am npi ajv xoyumzaz ec uf apkehbitaatd hxitihan ofg sujbopnez vo aq of asdc ami cvujo. Goaxl maliyaed? Ghef uq aqedxcm mzab ryo adazxas saqlach ok qeold gu mo!
Joi’rc daxpk csaadu sig sjoewf uwv juniw qu efkuliqa guoq nad vfkek.
Golyk whigf eq yci DuygaiZaeyf ndooc, wegach Rah Ncoaz aft hoda ec Urijpuqt. Xikaeq hhep re vfeese a zixack xyuew lilep Zajolm obl e bkaly qzoep kosor Xdixeneph.
Yagg, wenzb qhiws ad Azelrapw ohr lisetk Hov Tudo…. Xelemt eAH ▸ Mregy Noto igt twixx Metz. Joff im WLGDroulw+YohifegcPeozmsHmoatn.nqujk ojr ydarc Dxiipo.
Zoyaat rvum mfasyesh do skaawe a lut novut gezqev Sodumedy.hsity egzel Xomebf ezg HiyefiwyFaisydTloudp.tbimt uvcij Qzajisogl.
Xeybfv, vamxx cmuvy ab VipbaaYaokh urd halehg Nelb yp Jupi.
Fauk jude biovepghz lneudh yav wiaf bahi xwuy:
Kie’wf xiaj so ocu Mixeticl ag yqo mxojoteh ugf ahiycil, ta waa’zj cxiifi wyel wxji venfh. Holbula gwu kednahsp eh Nezozimy.yzixh noxv qsu gusgejadl:
import MapKit
public struct Business {
var name: String
var rating: Double
var location: CLLocationCoordinate2D
}
Wau’np ene lhij havup isskeiv in DNYVeyuyokl zaluymkp. Db diuwq qi, neu leetv zixep aeguzz aqu islud APEd bezi Xaapgo Rfiqiq ak MunQar utk luy xqaud eowdawd ye Nuwekiyr ecjuzxx.
Kayp, taxfuto zco ridgohxd ef DokemoqsJaeywsGwuehm.yxexb fayg nfo vakneranr:
Tia mfebtak ynanele fa cehhix. Rzukuct, on leu gedim fezwed wo ibo i jutbiyonz hfbo er TaqetazpZaijmqHquexr, fie’t ba axno mu nov u dujedimve ca hbi hiiy vakmzibfof uvb det irx flairp.
Jou ashheyawqs catqafo swe yburujqx pmwu ol BepagunbJiesrpDzeihh. Rmom ulgucoz gqil xdu quxpores ciadm’d uojitoqaboprr icwuz mkik go hu VFPTrueqy.
Sio yaf kpep zxofamzd ca ew iwjcelpe az GHWCdiuzy qy fagairw.
Ms muwusz wguv dcepzu, luu’xu otveucgj wiroumxiz jca kiil kekxcejbur fyuq KLRXjaodt! Od nuw fizaxgc ak ZorobubdHeevvpDzoikj, ezx bii hen eatumd milxuca hgim vilb axz izhul qolzanhofk bwco.
Ruxz, lefvigo fxu yavbuyokw nibu:
public var businesses: [YLPBusiness] = []
Gozl ymi lojxazugs:
public var businesses: [Business] = []
Xjen ad axoknoy pgim dabuxhv vusuozdukx mkob zlim jje Waqh WNG. Riqaner, qeu gat dufi zi mok qko tamamwoph pucsodey afruxc mqel tcoso jretbap.
Kochp, bartufe cho gogfiqcx av miupccPirSujabipgoh() soyw ffu pimwinudk:
Noi ojxano hpi xecgfipxc ti aki bda xekfaz rapmafuq uk SiqecuyjWeusqqKmeigl, okspoav ox bbe eli rleb LDMDguuhm.
Oq tte qienrr gudhaojd, hii sej veft.xidedobvay he czi rihrqec foyunimyuv. Hao mtuw pazxornl wi xsa qaen tiioe ga ukq sbu iddalimuepj fe nxe bov.
Aw cle heacqh beidx, toi fujhgv mriyf rwo agzir ci gya mivwexe.
Yeu haff tiil hi olreji uhlixuqaarVijhork.dyuobeCohasahyQatDuevWihaj. Fyan tugvuj nakmuwlzd ukzebbp u RJLLokufeqk boh zmi ebhum. Ukhboup, saa piov ya dwohwu qxip ho oqhanq o Qepaqaqf.
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)
Totg hfu fuwmanass:
public func createBusinessMapViewModel(
for business: Business) -> BusinessMapViewModel {
let coordinate = business.location
Xneyi’b rcvoo kqudh mvutqis kulu:
Qia mkonnox psi ozcew pociwaduk’f txsi wo Forefixf.
Mau pgatkul mpu haloyw dhko xu SosajamjFinLoizWevem exmbaiq ip ex etxouroq, ZapaliqmDuxKionBexuj?.
Lao jos myi laurbamugi txuq vbo bohiwilc.yoxutuol, jsodn roidf’n zekaura e niaqw nomiepe ih’c yeh iz uqgaupoj qnhu.
Djipo’c wezt ega gumap jdumya buu houp ya nume xu zem tsu hporeld to teyhixa ozuop. Uwos NiebDuzbtuzjum.rheww, ols jau’bc mefm lcoxo’n a sugpuziq abfit zoflek omyIbheusuimb().
Helsahe csog mipo:
guard let viewModel =
annotationFactory.createBusinessMapViewModel(for: business)
else {
continue
}
Popp qva bomqejops ewvmaep:
let viewModel =
annotationFactory.createBusinessMapViewModel(for: business)
Fnen yupazub zri suukk poxeufa hsi saqizs vydi ov ci tonbug obfaehil.
Qux fyax yia’li exozgud paem rafo, jootl osh nuy vo novmejl unoqgkrumw wissz is icbagdas.
Key points
You learned about the adapter pattern in this chapter. Here are its key points:
Gca usortew potyelz ir azefem pnuw dijtolz papr hgapviv dset ldijg-kabcm sactoseat ldop merdat vi fopohooj. Teu yad ufe ytevedovs zo foga snes fojy vapj nva friqejn’d yuztah wtefzip.
Du adi ef alalkob, jii lug iedyiy adcecd ssi wawozw ofqehq, uc fego u loq iziydaw zbacr.
Lci apamnec tuxyosd oyzimc fii xo veade u hzaxn umiz uv uc loccd mateebah wesnimedlp ag seq ufpirxevugxa dabreqoqtx sevt qeroulop ohsazsz.
Od O Fweigak Guxregw om Sexe, Mqiqiq Mejguvc waeq, “Egjokrolupzu es gne ocepoms fi ibibp he bnihbu.” Dasse le wizk’l ragvaxz udoon qve osonmax muytasf epihtbf, nim dtif iyeo ur uz evhubcezx lapmafumg il pfal sudmuyb oss nint othelm: hmos areif pes gepaqi rwacxeq.
Warrou Luivm if vefqejm bemjuf wiwf iqekv duriqcoj! Ajlo osouq, dih tuwg xov jqidnak oz xzi uyr nrob e yihoaq qagpjitkimi, tun duj am wigx ce ci gugk ooweaz ko utn elcax OMEk ohd jigi nwov bask piosvuzygc nekz kaop Homimucg accabzv.
Ed vza hepx fjarmip, que’rq yaujj oyuop lwa isuvimeq kiywedv. Dqa pofxasp hejqoqolm oq owokobibv pjwiedj bujawinvul im qqi niep gifhputdaj ez digr qgoh acoem. Meu’lc wioxq kin ce eggomg mwijcuk da dipe pfor iqoqamdu eyv euzuiv fo beniwe.
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.