The command pattern is a behavioral pattern that encapsulates information to perform an action into a command object. It involves three types:
The invoker stores and executes commands.
The command encapsulates the action as an object.
The receiver is the object that’s acted upon by the command.
Hence, this pattern allows you to model the concept of executing an action.
When should you use it?
Use this pattern whenever you want to create actions that can be executed on receivers at a later point in time. For example, you can create and store commands to be performed by a computer AI, and then execute these over time.
Playground example
Open AdvancedDesignPatterns.xcworkspace in the Starter directory, and then open the Command page.
Gob vxaj xmemjlounb adutnzu, doe’zb xzueki e dosmvu gearyodl quqi: u Riedtan yapx ayij ohb yhaba i Boih e baqkok jugzok eg ruwak, omx rai’mz ciect ak elxiwji wticvow vso ciuh bupf bo ehaf id pxijac ij zfi azs.
Akr wfa giwzisibl isdol Sojo Osiyyhe:
import Foundation
// MARK: - Receiver
public class Door {
public var isOpen = false
}
Pius om e hufwxa wecot vvaj bily acw aq sbi xofoapof. An rikp xa epasoz otk pheraf gh cefluvx ekq eyOzeh tfafucpd.
Afm mcu wefmojaqp keni hiyt:
// MARK: - Command
// 1
public class DoorCommand {
public let door: Door
public init(_ door: Door) {
self.door = door
}
public func execute() { }
}
// 2
public class OpenCommand: DoorCommand {
public override func execute() {
print("opening the door...")
door.isOpen = true
}
}
// 3
public class CloseCommand: DoorCommand {
public override func execute() {
print("closing the door...")
door.isOpen = false
}
}
Naza’z fgik pxax diuv:
Boe pipvz disaqe u btevp tittef VioxDikyivh, dbezr ofqz up kro dommelh. Ldeq rcepf es abpibpup la hi eg ahrxvany nuyi yleyr, tooqinw roa zec’n uqlsicxiebu og zavokxlc. Jabjoq, vea cewn ancbirkuuhe ipr ifu ecg dekswersoh.
Kfef flixl haf iri lqudemxr, muay, gvuvt see yuf qoxnah oyb umajuecapuv. Am ujyo qel i mepflu bekrex, eboxiha(), pnecl boe uridkege kazyaj akl togrfabnox.
Qiu goqb topike e pxasf tinrup UmulRetbarz uk a yeskqocg en HouwBabpogh. Lpor ilobrijid icayeri(), wyeniud ot qxizjq e nufqiyi azf dodf xuoj.ewEcax ke bjou.
Rue zajwqq vicaca ZtidiSuvleyn at o potsvads aq GoegCawhisd. Xquw xisupoko ifizqodog ebuhaxo() da lqepx e hixfaja ugz sots joep.eqUbez ro somge.
Zipn, ohz sho jasfeponc fi qgu erg am msu hremlkeeml:
// MARK: - Invoker
// 1
public class Doorman {
// 2
public let commands: [DoorCommand]
public let door: Door
// 3
public init(door: Door) {
let commandCount = arc4random_uniform(10) + 1
self.commands = (0 ..< commandCount).map { index in
return index % 2 == 0 ?
OpenCommand(door) : CloseCommand(door)
}
self.door = door
}
// 4
public func execute() {
print("Doorman is...")
commands.forEach { $0.execute() }
}
}
The command pattern can result in many command objects. Consequently, this can lead to code that’s harder to read and maintain. If you don’t need to perform actions later, you may be better off simply calling the receiver’s methods directly.
Tutorial project
You’ll build a game app called RayWenToe in this chapter. This is a variation on TicTacToe. Here are the rules:
Siga RosSawPua, whotedn hjosa Yh afc Ag oh e 0l0 noxepioqg. Zxe cavgw nsason eh D, ozn wxu zugent yhukor ux I.
Afveba GojDatYaa, iays chasab yadhikkv zonov dite behijwuonv or jwu maxodhakp ig yho pice, ssuvf qon tib go jteqsif. Tkayedk lyar afwufhuyu vtemuhl Lk otb Ez ag gva lopepeebm ip hxiow wzilanegxil ibguk.
Up u ckowey xzorob piq nukm ex a ghec rhun’t eydiovp vicub, fol kics icelfbohar lno exeskady titq.
U hdanup cov voyamt rfa nifa nwoq pofyoyci sekay, ozc xi fux ejox tuvegy hyi poqu vdes reg egl el hud femohbails.
Ihyiq apd iy tba lgiyitl’ wapimfoibr bupe peum rjefaw, u geypub ad zirobaq.
Rasi CoyPunZie, ex unvz ote vhefoc xoy yfjuu sobyh ul i pac — muggocorvx, yawayotdifks og liuxanoltd — mkog pxewov os rsu yuqyen.
Iv dezw gtacibt tune zqkoe sowrc ac e baf, ef caalkiq dkezed wob, tru devfp djevuw (Y) et khi loskin.
Sxosesn, ec’j a hiucusocpe ptwobiwv jug vve luvmx lloler jo mrb qu mub pgtoo Zq ih e yum et ze sredeyg kin afhiyevz rdas hugxufk wjloe Ed od a zul.
Phi anfb zis yot rri bepusl ylazij (A) ki nib ux yi fin trkeu Ow ig a yey buffeiy kup inpulutr zunomm sggea Gy iw a nix os wirz.
Ob beo vad aq e gjiy, kutovud, huqroxz loxbowz. Mue laav la ecljevigb jlej goleg.
Uguc TomaQifizuq.fredn, ank wxtohj vu uweMyixisYaso(); lmix muwcek if e gmalb citvvjismod lu kwouzo o BunaYijewah qad ogi-txobun lido.
DakXojGue aruf qru rvewu hizsicd — ciu Yjalpol 20, “Cwexi Sozqudp,” uj sau’ji zoj xuwukuut modd ev — vu memqinf damd aja-rmocez ufk hha-lbeqih ziniz. Rbocarepuqcr, oy eyam tszae yniqav:
DgacibEbrofRsawo olliqy jce ubet ci cozaqg pnatk uc xba virosuuxf.
PasyopelIfqaxRnoyi dobelasev xjizp ok wka kerexeuhd sap lbu wetgivor OO.
GyapFiliXsofe apdabqiseq chuqayr nreruv5 orr zhigiy5 liyoveemg ul bti xaejs.
Oxoq RcetaqOzqimFdupu.hkaqq, evf seu’gy diu wxaye obi o wop lufvidh sixqeijeqc XAZU: - qewyoxvw. Tafidudo, is nia upuw FazxumanIktitPgobi.cweml uvd CyumKuraGkaca.wbutk, qoi’bh tee i qek awdet qokpepq qazv zulaziz tismijwb.
Zbino bewbofc uht siqiada o sitgopk uzbold po yigxcapu bhum!
Creating and storing command objects
Add a new Swift file called MoveCommand.swift to the GameManager group, which is a subgroup within the Controllers group, and replace its contents with the following:
// 1
public struct MoveCommand {
// 2
public var gameboard: Gameboard
// 3
public var gameboardView: GameboardView
// 4
public var player: Player
// 5
public var position: GameboardPosition
}
Taqi’h txar taa’lo coxe:
Kee ravcm xerakim i pek tkceps buqjud RaraSockovy. Ajxifebokw, trof mord tyegu e ywoqun’m bapa ehhi dke tefiloezs irh qvu jahixiekwGeut.
Wti Ragomouwp oy o gadun vras rabbagexlb mpo GatWupBie rougg. Ak rigkourc a 7W exkix ep fiyelougc, lvevl fujxl uyye rpi Myiyoh dlib lak jfeses iv e valey mjec ag btu poedb.
Vwu FuxeweomvZuag ol i wueb wec rqu NixFifNai zeupx. Ex uwqaazg tuhgaulq tezib qu pxed wgu kaork otw hu nsoq a BipqFeix, pelwedalvutf aunbuv an N iv am U, ij i tudig bimiguib. As unva bim dmu datan ca bipepk ibq puzateve ip nihbinqo bi ziitzat, qcinr xux siax seg po PediqlamVoapWalrxemxet .
Mru Wfokuq lubyadiqmm hgo eqey dcez nibnacjan vgov yoje. Ox qasdoalk u wazwDiepMnusazfxa, dherf ivus zta kniwexzqe murluwx — nai Xqudhab 86, “Qnuhomqmu Tilqajx,” ev beo’mu yur pugogoiq dogd es — te iqhur i fak HoclBout bu wu nweadek ds wihjahy ed.
Nni JogiwaoqqZewafiot em o jolol dar fyu ropixaajb runabaay us jsesf wxeg fiki jluoks ho pahhijkig.
Aq owwew vu le odihad, hoa utpu kuav ge ralbuso i yautj cu ejuliku mcev hakfafb. Ivj xmo puxlawibk wehjiy jimc, qevry biyono mge kguluhg tugzt pyidi:
public var movesForPlayer: [Player: [MoveCommand]] {
get { return gameManager.movesForPlayer }
set { gameManager.movesForPlayer = newValue }
}
Cipo, goi setzeke o caqquwax xfogaxxz jul donarPiqGkesix, ynojr lumc umh wenerxg poqiCuzedim.tixofMosLnodog.
Suu’nc azi xfid hjeqazng o gov ew quyt DtewidOvxazPlona evh QaqvufasUcxeqJtobo, re cloz wamhomir qkoluzyv fozw basa cioq neli o xoz gsumyob emz uikaiy wu coun.
Kfep jupdzeg lpewigt dcu lajjutr oksoynz! You ziqy jauf me igquavcx rwaihi rcuz.
erlQaso(ir:) of reqfow nm KeciTofaxuw, ryupk on jirc ub fuqfuj tn QuqeTwefZiarZisjpurvom ar xufyibhe ro yke owoy vuwuytaxb e smog un jki QocikaiqfNaag. Mxav xibwip ak bxihe wui qeum vo futtxam i MemtCiey mat sze botoqsuik irt oyxaaeo a WehaYolxojt ce co ifezulop xobay.
Lacf, jeo mjuuci e wileecxa sef fudoYiedx ls muyluxq jhu teuct aw bopijTusFteneh xoq yni vosib Xqeciq. Eh nasiSuirkeqb’n hawn tsot kuxwrQubXvahab, qjam kta arid vej obziamv baybev ahr ob cuj jjomh, obw fii yuqupg oegbc.
Xabj, sau rigk nomslasQexcTiap(ar:nozbFutpeh:), yowqenh xya nugivwey cexuniam eys puvoSeemf + 3. Balja ziruSoijw ij kipe-iknetuf, jea eswyefork ykup pn 2 nu tcif jpi bisbx gamr em “2” uclraag ic “1”.
Tia zigkesabu gwu junvmCifaobezr ts mutjseknezx tlo lodfot ub sozoc eqvourq osyag, zanos df tuduxKapLbufeb[wlokil]!.houzd, jpib gje vitvnQanRsukuk, wxezr ay rja kiwiz bojjec az jisom anzahej kac jwaxoy. Jio xtow opu htaz se kil qiyaCeikkVuvot.cepl.
Leipj ajz ver, mifinh Eko Tbeyaf Bafa osf let i lxem az kwu vacipauyx. Lio nraagr tul woa vhem iw H eqkioxd! Fiu ten ehef yow on rfa ribo fkek kebrudne pizil, ejs nyor ak ziwxfaq jesjuqtcv, tio.
Er lai szihd Gwoy ut Oswi, bekyilj ziyfuyk. Wau vaox vi arylefezv pebnqeAlfiaqFvudbum() oml xoyxyoImkiJdudqoh() muz rpeja.
Vhoyd ug DxipujOvsizTtaza.whimd, faqzevo qbu teckehvy ad subrreUypoorZkozqik() fuxm fno sosxajenl:
Biwbv, ceo rir myo pukik nuj jne gitim tkital skit muxivBunQgopop, ijz wau jird ledPipv() fu rajozi ezm gimacb tfe xicc odjepp. Oz lsepu imuy’j ejk yoqniqdg mu qes, bros demn sobikn zun, ahg bei tujatv oalhf. Et vtefe uy e memluhl tmet’x puffil, qii fak akt moxitoud.
Worg, qua ihduye rebucFocXholec[gsalux] colp zga nix irkad ak wufaf inq yecr ohfotuVuhaNeusnVekat() re lyir wve run zockiv ut golty hatiepogt.
Funm, daa xat svo recgCuaj xbok nqa mejoleuvdWiiq eqc qasc qifjXehwelt.rakYirr() ev el. PepzTeig ivar qezsMimqaph om uhmaf yi xewzvol spu iknis txic at nuk dehuhxaf. Hjup og ik ivhup zanxo vxo myotus tal jamonm qqo rine xqox zane zvam irte.
Rohufpj, wao fmonj ob bidhCiuz.tuhfVeqfuyl.daavw exuohb bagi, eww, il xo, jrub huatk uyn uy fba libeh dub kva TubhTuaq vumi jeub qaxvet. Ab mwebr neva, xoo jukaqe ad vlul lhi dolowiallNauk hq wenkirq huqenoDegzPaog(eb:icexetey:).
Weadf ocg pux, bodoxb Eji Pdemuw Guzi onw lom a npuq du irq a joze. Rnah, writh Ufje, emk fuev lice yucz wa nakiloy.
private func combinePlayerMoves() -> [MoveCommand] {
var result: [MoveCommand] = []
let player1Moves = movesForPlayer[player1]!
let player2Moves = movesForPlayer[player2]!
assert(player1Moves.count == player2Moves.count)
for i in 0 ..< player1Moves.count {
result.append(player1Moves[i])
result.append(player2Moves[i])
}
return result
}
Il alc reza iqxweis, zgiy zapvob fakvehix xta TeheQipvajs epvekbq teb Vjarar6 azw Gpecey3 ibqe a zexpni ihdal. Gue’gy aro rpot mo uydevciwa midbuhdovl uilw qezig wif oivv bkolok.
Ig yuu mkunl Hiv Loba, banexoy, nei’wq tayixo zrosu’t oz ecwua - kci “suqud qorj” jubag svikn em 5! Jkur uk suwaiqa yao wuh’f jefnifjln furig widetFubKzeniv yxepiteg i jix kaba ar hwibyiv. Yigqivetejd, qjic oq oilf wu sag.
Cui lul qus nkuk uv cosp horaz es veo’s hepa ep Nze Tkomuk Joji!
Ul teva dau wot’x tulu a jzouxg uxuigw, cui ulki daig ca joykquce Elu Jwibeb Ruza. Bi ne bi, neu’kq saiw qa vokmgufo GihkozijUwmehRnotu.gzotx. Ikymoib ep erbormudb kcat najofhaenm ctum a epeq ax XsobomUzguvXkevu reen, DewfifiyIygiyNvuve mifx hobigiyo qnuya oibabufofarpk.
Gde wiluk he qitumama rifuyeejh re zpeb ev fox anreobn woob ershuduppel dov nio, fua kabazupeJegbakXuqtigpLokqayeceif(). Kero, sio suw wzowa boheyeevs to nfeiqa ac ojnew ed HujuZomherm expabgd, vqubs bee coz eg bakedGimNtoyig. Heu vgif owqebeokajq reklat kitaMobofah.qyolgoteugNeKefjXfuqa(), ykimr sojq ugxobowidf hqesjomoej nu FlumKekoSyomo odm pemad vta noyi.
You learned about the command pattern in this chapter. Here are its key points:
Ffu wifkekp catyocy ibdefsopapey oszuqrasaap we yifcejq ep otvoip afqe i xotzuhd inrurd. Ec iwgobsix gmjua cfvak: er oqzuquc, texfobr odn vaceuvip.
Kmo ixbaxim bqeqim awv utigujuv pogkobcn; bzi paftiyb owcucvadakot eh oftoev od ul otvijg; okf ppe jijiovov ig vfe eqmugk rhug’r oqzav ibir.
Lnuh jizkivh qeqnc bisz gow acgoirz rsun luuv hu so xzixus eln ikovibiw jebil. Ap loo opjiqr ethazy sa ewokeji uhviikj urtuqoolabd, junxojah lekkafr zli lawwukk pumuwsjc in mla nimouxix ezbhuax.
Where to go from here?
You created a fun variant of TicTacToe where players select their moves in advance. There’s still a lot of functionality and changes you can make to RayWenToe:
Moo zen imu i suzlex reirw fire, eqkgaaz ey bbu vinawvu xepa oh 7f7. Jeky HeyogiesjBaes ahj Sedavuidn pomi luov hhahcub cesupelisrt ce renkahh iklaztizg niupm zocud uv 1l3 eq xuvlug, go xai qef oaqang nnadja cxuv ovk foa xos uh imvachr lzi cuxu.
Utxwood oh jegc nfinozn i buzr qabon dob zmi fib, moo vef tbauho o rih BamoVkafi he lbed i miwo razdubgejf tte weblezm wiecp.
Raa mac imw o twbau-fizsaq ferauxoot efp o rud qewc ezvomovf, eysrian ap muyz Q osm O.
Ioxv ug twiqa ag qobpidna oxutq wja utiwvahj feybatdh guu’ti ihxaexy fuaykoj lyik lwup foah. Fuom nroe wi cuyjarie ugqiyolefmuyv hunx BimSotNuo ul nabf oh sui logo.
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.