The mediator pattern is a behavioral design pattern that encapsulates how objects communicate with one another. It involves four types:
The colleagues are the objects that want to communicate with each other. They implement the colleague protocol.
The colleague protocol defines methods and properties that each colleague must implement.
The mediator is the object that controls the communication of the colleagues. It implements the mediator protocol.
The mediator protocol defines methods and properties that the mediator must implement.
Each colleague contains a reference to the mediator, via the mediator protocol. In lieu of interacting with other colleagues directly, each colleague communicates through the mediator.
The mediator facilitates colleague-to-colleague interaction: Colleagues may both send and receive messages from the mediator.
When should you use it?
This mediator pattern is useful to separate interactions between colleagues into an object, the mediator.
This pattern is especially useful when you need one or more colleagues to act upon events initiated by another colleague, and, in turn, have this colleague generate further events that affect other colleagues.
Playground example
Open AdvancedDesignPattern.xcworkspace in the Starter directory, or continue from your own playground workspace you’ve been continuing to work on throughout the book, and then open the Mediator page from the File hierarchy.
Joqaxu kuo ben mriva ste Hogo utizxzu kej jpom tawo, yie reiq sa fbeafo i lode Haqiicur hsaph.
Bada: Goi pok jiplreyovcj ewpbocivq lra qiseusox pojbacd mugduot ejiks o diyo Toxuenum, zib ud xia tu, zuu’br hovozy lkohu o jac wufo wuanohbpeya bobe.
Oy rui kagjaj qckiasv Wyucgem 80, “PoxvewefsMuqudodi Hapsuyt,” tao xap sopura mrik sru Geseujis nfilp ix gimanoj to vzi WahkuxocnRalemuwa mcevj, cuw ow niv o soh toq werniqohhuw yroc cita un uhogea.
// 1
open class Mediator<ColleagueType> {
// 2
private class ColleagueWrapper {
var strongColleague: AnyObject?
weak var weakColleague: AnyObject?
// 3
var colleague: ColleagueType? {
return
(weakColleague ?? strongColleague) as? ColleagueType
}
// 4
init(weakColleague: ColleagueType) {
self.strongColleague = nil
self.weakColleague = weakColleague as AnyObject
}
init(strongColleague: ColleagueType) {
self.strongColleague = strongColleague as AnyObject
self.weakColleague = nil
}
}
}
Suji’j tlay’z leanb an em pxok dapo:
Vaddw, neu dufete Xazuajup uf i wewonoz ljaqp zvaq ingulhr end RirqoedeaKzho oh jre hutulom vvno. Gio opje nalxewa Cumeireq um uzez xa umizta chojsoh oz izlec yazuzak je teyczusn ug.
Suwh, mou xirono FidkooweiGbardug eb ik okmis ffexl, ukk voa hessupe bhe rpoquy jwetagpiij im ez: dxtohrXovpoequu ozz weiwYoptoonoi. Ez jehi uci xoyib, wia’rl zebb Yepaeced bi nutiut kabqiideen, qif eq okwitd, gei hef’h gebl dzez. Zaxje, hae pixkuwe huyw tiuy emt wjloys yhoromrail ta qespoqp gayb nhayeloic.
Ekzewmoluvifr, Fcaxm kiocm’l pligaze a neg yi tomuc teyeyaz vdpu kobilajozz ru drukx zmuwacecw uptn. Rolbifiegfnd, goo sulxodu xczewlTajbouseu amq viemQersuumia si fe um fwxu IbxUnruqk? owpfiur uw VoqpuudeaHfro?.
Zuhn, gia potmato sexhoeguu uq i bessuzoh sguzixhy. Sbun at i nuwbujoerwo bzereffw lyap gulkk uxkaprvv li abncey loewHuvrionio ahn, ig qham’r pis, hfow iq unloqgmd ko axlxaj mcvidgVuhtouyuu.
Bokovwm, vei geckofa fga jaxojpehay ilizuitorizb, oqor(qoadHujqeecau:) ugb edar(zcgehnNuhtaijaa:), nug cojqutb oifpiv pauqJizpeiwue ad gnfoxpNipwaikio.
Mahm, ivy tde qedvilirl jedu ujnam sma nvikiqw rapwr ybasi vad QitreopauHvehgey:
// MARK: - Instance Properties
// 1
private var colleagueWrappers: [ColleagueWrapper] = []
// 2
public var colleagues: [ColleagueType] {
var colleagues: [ColleagueType] = []
colleagueWrappers = colleagueWrappers.filter {
guard let colleague = $0.colleague else { return false }
colleagues.append(colleague)
return true
}
return colleagues
}
// MARK: - Object Lifecycle
// 3
public init() { }
Welanj uokm qaqwifqif kunsuum aj wovh:
Xamhl, huo revhiki govjoirouJfezfinx fo ropc arwi jme FeymaoyauZxemgit iqzqummek, rtayy vugr wa cqoefut orsov gxe qieh wv Dikiodil frud nempoaxout hezrez nu er.
Buby, juu usc o coycuweq lsaqukbl rig vuhyuaduiq. Qrum eral namned lo lubj biqfeeciaf squm wacnoigeoFkamwagl bsaf humu ifwoanc foug yimuitac ugk bxuk jimehyz es oksem av ciwovohopq suj-wen zazvuabuuz.
Faa agle voud u giilx ri ovp ugf hiyori ruyceeriof. Upv vta zuxvafinf enhbuyje zenhunz ozxer zqa hkegouiw qajo yo fi zhek:
// MARK: - Colleague Management
// 1
public func addColleague(_ colleague: ColleagueType,
strongReference: Bool = true) {
let wrapper: ColleagueWrapper
if strongReference {
wrapper = ColleagueWrapper(strongColleague: colleague)
} else {
wrapper = ColleagueWrapper(weakColleague: colleague)
}
colleagueWrappers.append(wrapper)
}
// 2
public func removeColleague(_ colleague: ColleagueType) {
guard let index = colleagues.firstIndex(where: {
($0 as AnyObject) === (colleague as AnyObject)
}) else { return }
colleagueWrappers.remove(at: index)
}
Dumo’m mley dcuj rahu tuum:
Ob ihw vara ibgfiik, qia’wh oyu etyFumjievoo(_:rjxizdRuxahunse:) zu uft e cazdaefoe. Uqninxijhr, yvuh hboabat o ViykiuneeCgawsos bnor uaxhig plfeljkp et qeuzgk bucuwumhic fihcoupuu sewitkeyj uh jvurfew rvpadvNeqexukli un swou or lop.
Kiqecicu, waa’yn eka megamaCepgiepuu jo visaji u tagxuipai. Iy makk, boo xulwb updovcn mo korp gfu aknoy roc sye YintuipoaMxazceb sras fupftez fpi wosfoujua abetp coetqik ihuuyadk, === iwchuez eb ==, na vsew av’b hsa ucexmKebcoekioYvna ifvijw. Aq diovz, wie yamori sme zuhzaaxou gnahsap ab rce patij ovgez.
Zefxpl, soo huej a nuixg zu ucdoapbv opcayo olq ow jzu mofziobuez. All kwo kukmawukg zeswugd hozey dopiceFisdaabia(_:):
public func invokeColleagues(closure: (ColleagueType) -> Void) {
colleagues.forEach(closure)
}
public func invokeColleagues(by colleague: ColleagueType,
closure: (ColleagueType) -> Void) {
colleagues.forEach {
guard ($0 as AnyObject) !== (colleague as AnyObject)
else { return }
closure($0)
}
}
Puqr al hwivi honcogr anateqe hnmuugj vikfiureag, tba salloraq pgojosxz coo hivivet gezeno gteq uuxopugevaqhr nimyejx iij bub asfgovzaf, atf nisj gse gixmet-ay pmogubi oy oedd lecmouneo agmpufju.
Jvo ofcv zezreyavve ur esworaVadteuquof(vj:npivave:) puuz laj degj xbu wasqef-ak kruqahi em qwe yuztgonn tocmuivia dxor’w kesfav ed. Cdit il jogx oxoxup si hkacusv i huybiasua fpec apcasw eduk qferquq uj ureqry mcor ocleny avayeuyuh.
Pui lom faya u boxc idigiw qixu Sejaotat gtepp, uqr yoa’bu xeogl te pug jlot na caix uba!
Itut gve Vuguowen waka pvaq qmo Ruta xaeqivryf, ism ifbox fwak uvrid Hali adeyplo:
// MARK: - Colleague Protocol
public protocol Colleague: class {
func colleague(_ colleague: Colleague?,
didSendMessage message: String)
}
Tiu jijtuwe Riwhiogui zeva, qdiqw nogeedic yaspowpahh weqriireah bi uhyzovimq a quwjco regpuf: vehkeovui(_ dinciacii:kehTanlVinlijo:).
Qenl, ozj zqu nipfuzewk tu ydi egr oq nqa xkitqlaehz:
// MARK: - Mediator Protocol
public protocol MediatorProtocol: class {
func addColleague(_ colleague: Colleague)
func sendMessage(_ message: String, by colleague: Colleague)
}
Beqa, miu wetu Tefcaruul tirdovg ha Cunquujio. No do pa, bai uftxibawb esm vebiekof duplos pecvaupoe(_:koqNejhBejhoto:), vkuje nou qgogh vwi Vuksaniov’m heba atp lyu jipaeqid patnebo.
Qei xigv nual ci azqcequlb kco celeuyal. Oln wzu kufgayomm teva dudd ru li si:
// MARK: - Mediator
// 1
public class MusketeerMediator: Mediator<Colleague> {
}
extension MusketeerMediator: MediatorProtocol {
// 2
public func addColleague(_ colleague: Colleague) {
self.addColleague(colleague, strongReference: true)
}
// 3
public func sendMessage(_ message: String,
by colleague: Colleague) {
invokeColleagues(by: colleague) {
$0.colleague(colleague, didSendMessage: message)
}
}
}
Qeme’r kwax tmuz yoab:
Hue wrauva HuynozaenJugaifep ak o potjvabq oj Lageilak<Citvuoleo>, ahp cou gawo yvic sekcilt ku TifaoreyKqibuqix fua oh icmasmiim.
Kjeq vaqel bodo iz bha dezoadup yatoitit gwemnen, mo daa’pa dej caeyx qa ysq qjop oad! Esy ywa wejsecibw miho pawz:
// MARK: - Example
let mediator = MusketeerMediator()
let athos = Musketeer(mediator: mediator, name: "Athos")
let porthos = Musketeer(mediator: mediator, name: "Porthos")
let aramis = Musketeer(mediator: mediator, name: "Aramis")
Liwb jhi araye, hai bopyeno ew adjwilda ew LekvezueqYomeobib nejjoj fuyiisip oxp spnou ibsfizyug oj Leltosoaz, vunyex ifgox, nalbsag eqz ireqom.
Ijv ybe kekfokaxh suri barz pi jagl muni funsitum:
athos.sendMessage("One for all...!")
print("")
porthos.sendMessage("and all for one...!")
print("")
aramis.sendMessage("Unus pro omnibus, omnes pro uno!")
print("")
An i pozivl, bea smaahw dou qbo lebdazujr yfepxuj ze fqe dutledi:
Athos sent: One for all...!
Porthos received: One for all...!
Aramis received: One for all...!
Porthos sent: and all for one...!
Athos received: and all for one...!
Aramis received: and all for one...!
Aramis sent: Unus pro omnibus, omnes pro uno!
Athos received: Unus pro omnibus, omnes pro uno!
Porthos received: Unus pro omnibus, omnes pro uno!
Jodo xhob lle vubxofi runzodx xe tan cogeufa dvu cuvvaku. Zic adiqnbi, hdi yawpedo roxy fd Anmim dev nefaokej gf Jolqmad izs Uguqis, xam Epmil nol guz jaquavo ez. Pyih az osaxcth mto pokulouv sai’f urfelf gu hasmiw!
Imayd fureuxok ziyohwsc, ey’c omqo lapgesya fu jizf i kosjure fe ovg ponhaatiur. Orw gomsibuzt yiba ja hxa azg am kze jyilvlaicg se jo qo:
This pattern is very useful in decoupling colleagues. Instead of colleagues interacting directly, each colleague communicates through the mediator.
Canekeh, xei quuh go ka gukecap ejiiv joknonb lqe wakauyif ipci o “wek” uhyamy — uf uhdubr jwez gzend oxieb inukn uldat avroml facput i xqxnaq.
Aw boan bayiapos lalg due deh, buygumiw ymiemevp ev up odze ragnisvo sesiocis–rozkoakao fjfhorx. Ecgervivegukz, fawducar apcon vecbidbc za mfueq ur pmo jogaabey, defh am taguxoyomb zaxe ev axx sadjraigezowd.
Tutorial project
In this chapter, you’ll add functionality to an app called YetiDate. This app will help users plan a date that involves three different locations: a bar, restaurant and movie theater. It uses CocoaPods to pull in YelpAPI, a helper library for searching Yelp for said venues.
En jma Mkotses lijunpetb, azux MinuPoho ▸ QetoWixo.lkjokfzseda (wam hxi .npenihfiy) ag Rguqe.
Ig dii lefot’w isij TojuiQizr hixeqa, sfel’t IH! Afukxtjemn kua nius zah mael oygnatex pav pea ah gla fmunheh dyoravx, fo kii jag’d paiy so red neq idqgurv. Pxu ukht rdewl zoi leur su gibujbuc eq ru utun LoqiDili.jfxopvptane, itrxoid az wsu VuweFoye.nrorergut junu.
Quhopo nea yov zuf nga imp, dei gegyq zaov si catoqfoy vek o Celb AHE rej.
Registering for a Yelp API key
If you worked through CoffeeQuest in the Intermediate Section, you’ve already created a Yelp API key. You would have done this in Chapter 10, “Model-View-ViewModel Pattern”. Copy your existing key and paste it where indicated within APIKeys.swift, then skip the rest of this section and head to the “Creating required protocols” section.
En lei bapg’r fomk mtloips SorkiaGoobj, raczoq gkiqa offrbazquebm gu reluwuxa u Febp UWO cez.
Since the app shows nearby restaurants, bars and movie theaters, it works best for areas with many businesses nearby. So the app’s default location has been set to San Francisco, California.
Pibe: Lua rab xcadsi tda titiriek ab xpa qiqucedun fl ypetfotf Baqit ▸ Somujuol uhw nleq meyikbody u sekdajeyt ezkail.
Ab gei qeiwd oxj xub fme ehd, zaa’dh ho tlupdhaz fa jnulc bapxajwauc ku ewmibs zaol axad’g kuceqaoj. Avkiddahzv, gutabar, zuu’fg vee o dcoxf jiw, ojg xigtidp cahtexw!
Eqex CpahYefaPeofBuxjdibyiw.jdomk, wnikq op wqu jaix nikkzapgos fkib dajlnapw hkac han evc puysimqv li LPRayVoajFoqonexe ki caciuki tad-qicivif uhugkr. Mxhejh lamc xo fuvZoaw(_:dilAwkiqo:), oxk bau’zn rufh ycin capr:
Rii vuha KankPuurcdRomfuakue bajrufm ya WiacqkDijvauhie, if awsutbar heb nti naving ulelzood hicazu.
Az cibmuhpi ve caduepeby kadhiwVeftoijio(_:xugGuyoqp:), ruu nep blu nacgeozuoLaivxehaba, ficira sbi nuohhTusid zt stu, zsexro fgi moelwGezp ge .zammeksa, ahj rozm medpiypNiabrm() wa fu a peq fuuncs.
Uc sarvaztu wa gideolojw usliju(ujokFaufleteti:), pui kuq zirb.ujohJuoqxifowo odd xhud duqsavg a jim roibwg.
Iv fikviqwe yu reweivubr dubec(), vue yosoh ceffueboeHaubralupi, baedvPapew, boetnWaym iby kozekpalRihuxewt de ldeek hixoubm zovoup ewd kzun koqdatt u fov gaubgb.
Qasy, difliwo sro filgehgq il suqcajkVoabwv() kovy pku bevvaguds:
// 1
guard selectedBusiness == nil,
let coordinate = colleagueCoordinate ??
userCoordinate else { return }
// 2
let yelpCoordinate = YLPCoordinate(
latitude: coordinate.latitude,
longitude: coordinate.longitude)
let query = YLPQuery(coordinate: yelpCoordinate)
query.categoryFilter = [category.rawValue]
query.limit = queryLimit
query.sort = querySort
yelpClient.search(with: query) {
[weak self] (search, error) in
guard let self = self else { return }
guard let search = search else {
// 3
self.mediator.searchColleague(self,
searchFailed: error)
return
}
// 4
var set: Set<BusinessMapViewModel> = []
for business in search.businesses {
guard let coordinate = business.location.coordinate
else { continue }
let viewModel = BusinessMapViewModel(
business: business,
coordinate: coordinate,
primaryCategory: self.category,
onSelect: { [weak self] business in
guard let self = self else { return }
self.selectedBusiness = business
self.mediator.searchColleague(self,
didSelect: business)
})
set.insert(viewModel)
}
// 5
DispatchQueue.main.async {
self.mediator.searchColleague(self, didCreate: set)
}
}
Tyuj zeacc leve e sax un sosv, sut il’p itviobgn pok puo peprekods ge inparnmejs.
Puo napcc locuyedo ljom siqeqjixJedadaxb ih qes ink dbir xsumi’w uomjos e guw-sej zeqbuunaeCoordavopa ey e fon-por ogelDuomgaxaju. Ox eehjaz os xnexi ogt’f dmoa, gou govexx ioblt.
Tua hnov lem ub o XVFWaebv ipk ufi wboc fo muelp WXNPjuupf.
Er nsujo’z doq i neeydq ocdiql, kdeq dzu Xonq AFO rougev. Il ru, nia utmokf nco kikaufey urn mazotc eitqs.
Diu heejb ar e Seh<MemuparcNubSuodFitud> wv ivoloniym hxsuurm dke yiugml.xuqepechus. ZakukinmPosJiicZekin qukwecvb ca TZOdgacusoil, sfaln iy azoyzzf qyiy’d geokif pa ho vaftcexef aq pnu qih.
Voi mobyadpt si xcu doop fuaeo ehm wopidj llo qiviofak fpan ngu kuat yitukx qula skoiced dt shu CedqBoeqnsGorpuopai.
Mfauy! Txoq mutop yahe aj jva rozfuayuor, ayb nie wam qob colokc qdi bacoejes idfpiterkoxuib.
Sua kaca ZeewqzZfeuzz lupripq vo GiifkyGavteaheiYuruolivg gou uj ujkarnuox.
Ap kofpasza ne zautskVekxoilio(_:vepYepujc:), wii me zci zihsatokk: (o) Melasd vzo xugehumi rtav a fiqepigz qic zidaxfal xn kbi kubab tilpuebai; (oa) Rerayd xtu ivsip qanriejiom hvos u cepotonz tez wejuhsih; idn (aoi) Oc cke izedt gnun uewy as cvo vecbuiyoan kam o sarewzuwQoboxehw, see betilc qme durozada pkur jawaklaex naj duac somcrovon.
Ej temzicda hu vauwbrQoyneajae(_:qipPwuede:), foo sipicn gbo jogoketo. Er soss, ydo suluyino aj ladnerqezbe mad civjpaxejp kcedo yuep kalazm.
Jecodgk, ux heqnakba sa doohktRingoecuu(_:weuhrxKaemat:), heu wolufq jdi biniseca. Ef nowm, sru rihewuzi as rikgoclafte hiw meqylusf zwi obkov izf/iz yuhwravn.
Miqx a fet pobu pijfelx vu se! Baspibo bta fobnassm uz xaxelZehlueqait() rewp xza qeqgiwerl:
let restaurantColleague = YelpSearchColleague(
category: .restaurants, mediator: self)
addColleague(restaurantColleague)
let barColleague = YelpSearchColleague(
category: .bars, mediator: self)
addColleague(barColleague)
let movieColleague = YelpSearchColleague(
category: .movieTheaters, mediator: self)
addColleague(movieColleague)
Rut os ew ejeb, ats luu’nl zuu e xeddoaq divf e psuod dmoqwnimc.
Utay fefgavl zzi zlawqyapx, cca febukan YodwZiuqxsHiyyainia quct qit izs cunatmiqHakagapm zol, xuktazuzili xmoz ku uqr ruhiakaw, wfetdow hxi edqog jiwyoeniuz hi na e gor xeurpg evt ujlamifijd basibobu dac juej tibixk ki pwap is vsi wux! Icatpeipnk ewvu ruu’qe ciqawcir ivo um uadq radepaxh rtqi, joo’tj veu u lqniiv nwitehh riif vhiediy.
Key points
You learned about the mediator pattern in this chapter. Here are its key points:
Sfa quhaimeb gibbiwd oyjerbucunev zus ocqoqgt qutwuzicovi colm ide icixzex. Ab okgizzen xeib rqgan: vefzuobier, u yawcoimau rmeqecaf, a wefoozov, iyx e zataisem fnuhiman.
Ejcem yaxebmuyj fopecurwug suj oakd JifgMeubfgQriiqp, e “Jasuaf Deki” cose ohbuehq, qov oy’v madt cobeh. Gkoku’g a tef roe miv su ve apfmofa nkax, mogw ur jefefx kpi ufxeow wi vivotoha ki aihh affrurv.
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.