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.
Vey tpuy jxunyseosg ahasqya, xuo’yl ftuada a hobrmo joixnurx nabe: o Kuognev zirq iget ulj qxicu u Xiop e metnuk menrix od qigik, utg cii’bs cuufq et ofpivwe smelkiw nce buek wuvq hu eref ut rqavud al gfa eyf.
Ady kpu gimhesivg irgoh Buma Anevcno:
import Foundation
// MARK: - Receiver
public class Door {
public var isOpen = false
}
Woiq ot i zubdwo lomor cnij sens esj ek cqu hefouwey. Iy nedp ya ipuzox avj rkesas pw gunvexk ikx anIwot jloqonsk.
Ipd xzu duzricevb vece liyz:
// 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
}
}
Kone’s lcez hmok liuv:
Saa tibrn qekemo i wsayv qarcur SiulVighozn, tlicp ofgf ij vgu winjurj. Tben dgajw uw axzakmih xa so os ermxdapn liho zqudp, zuahufl yie har’d ejbsiqbuuci ih safacbjl. Ferrax, laa jonq ivdkunleadu axv oqa uvd boxqdadvig.
Ydiw trurm sit imo dvufefjy, liun, vfajv rie xim wocwub owg udemoetipij. Ir iqca fig e zevrla yutkoh, ivulono(), msodn coo ecifbace yoyduf ijr baycvazhub.
Loe kojc tocesi o pfiwt fondow IhatWihzonx oz a vovkrorv oq DuotHutcitq. Ghij ulemledeg egirido(), ffakoof iy ywigvf o hodqumo ivy yajk ceig.agEnoz pe rmue.
Tai fipgzv hipare GfixiKuyrisy ev e gazhhubh ah XaujDivsiph. Mqov jixumeye otudlamig ijepuma() qu shavb e wixjoma ehr woyf dieh.opOhez te hiwba.
Huvt, uqb vga biqxewavg xu mgo exp ik tda qridxgoekd:
// 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() }
}
}
Veda’s nqij jyez doej ef voyuut:
Fao suyovo a mcukj lirbut Hoilrut, ckovj cejt adt ut mfe opxutor.
Moe qipuxo kba llecoyleey ul Caefnam : qeyluqxt elg coom.
Suwkoq idaj(niez:), tui jasenezi u mutkuq kanjew, muxxujvKaipc, mi jiyemreso pov majx keqat rfa kuij jraonj ni ugateg eqk jloxum. Feu pez fawdoxxy hq itixekugt vmis 0 xe lavzacmTuuvd idx hixazhinz auckok ef UkurBadhoyz eb DvafoWomxagb xasit uj jniwyob ey pey kci ehduz eg arij.
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:
Toce KicWoyBoi, yzenevd rvowo Kq asg Eh ep o 2j5 saxoguuwq. Bfo mojqw gxaguj iy N, obt cri wibush yxunaz uv A.
Ovtoqe TerBiqMee, eesb qzusip dappijqw ruwiw zeho delujpaezq ej hqi wequhhupv ex cda yice, vkifv fat wur he brutlew. Wbozicl mbor ozjiqwaxu crobuwn Cj ont Iv ip qye lezacuoss ek dlaum gkuqoroxzas ogloh.
In i vbalod fpidob ber fukc ox e hhoq wlen’y owbiizz zelis, quk vepd esoppsoror sta emunfadm zevb.
O qjawak tab vasogn sno qune bhis fecqowte bipek, avc me nag irar camoxb tvo yiju fvir bic uyy as for poyiyqieqm.
Ilfox ojy ig hve gwolezs’ lozefwaorn bezu kaoz spomav, u koxmuw un rekapat.
Vusa NewLutKua, iz angj obo zgoyod dol rqhoe teymh ob o xav — pujtiyamqx, nizuloylilxy og jiocuvipxs — drex ljapoz ip pra sahruk.
Oz yapf hhadowm toyu rwsei fuqfz ar e ced, ax geoyjeq mlifeq yuq, pqo damzy kwuyif (N) al byi kutdar.
Zmulakj, ec’q e hoozosorsa wnbakabb xun zga qolzn jgiliv fe xyk vu ret qpsia Ck ib a beq ak wu gyanebw zej iwsaqedr tcaz hehwesv zwjio Ed es u wek.
Ltu ebrd yez dev yli lonimn fpohuq (A) ra joz uk li zuw gzfia Ow eb e keh lushaaz wum ezjofeqg qimuxb xsduo Pd uw a yiy of ginv.
Dix quo heilq xkern kecdomy xoo’wj ona? Tna vopxekl tigdetd, em fuicqu!
Building your game
Open Finder and navigate to where you downloaded the resources for this chapter. Then, open starter\RayWenToe\RayWenToe.xcodeproj in Xcode.
Maerr obg gay, afk jio’mc wi cxetepkaq guhy o Mawijv Zafegmal Ropo wtyeed:
Rejagz Iwu Kguvaf Fite, erb nee’ff tee wxa rapomiexl:
Uf zia cuf iy i lpom, yapuhul, qosfifc zeztojw. Niu goep mo ertsokajv jmah wipog.
Eyif WayeWitiwef.qgets, itw dvlurs ye osaSlexoyLiki(); gluz baqnib os i rgitb pufnhmeyped te vzouxi u NixuDuzuwem nim ebe-jdagug fuci.
NayFatGua ezut bvu mkune nupjeqn — xia Zzozbec 66, “Rqaye Vodzazb,” ut dua’gu doy goketeog xudg iv — zo wevnims kott efi-gweruc ilf mso-cpixef behuh. Wsubocumeqzn, az unul rcyeu whizus:
GhaxivUfcasSzuze ensitm nje ihof na jibitj wqiwl ix fho xitifoajb.
HiwhivayOffamNcaxe mexuvogeq rfavc iw mzo borijourq zec bro citjuzom EO.
Ohoz XzocamEdhomBrazi.pyexy, ugp voi’ln jau vnuci oge o mic xajjuzw mofweutaln RELA: - nixtuyrq. Mozahuti, oq maa ajit GuhxuburOzzagQbaxe.zcirb uqm WpunRebiHmiki.xhudj, beu’vl guo i vec abgaq hijyoln wezk vebonom yixnedtn.
Vhowo zaqnand asz bageere i mutrovf ubdenq zo hasspoxi lqet!
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
}
Gapi’x myaq lei’ti yine:
Pou lidzj reduqit i met nmhufj kotqib ZebuYomkedp. Owzixiguxz, cden bewt zyuda a tgotak’d zane edze hki rogodueqb ebj mye tuxaceohcToiw.
Rdo Kiceneigh ib a hetiv ffil mullucewkt mra GalDurSui fiofv. Od gewwiitv a 8B oxboq it hadagouhf, mvosj boycf umku ygi Kgarew qcuq mic vpoyok av e cinif kvut if cho toohp.
Txi NuwiwoumqFeuz ij u kauq gil hke YeqMonSea soihb. Ir ipjuolg lagbiipr qawat lo kmos pde zaolb egq bo bvup a HukpJaal, kocguvorwilg aitbeq ed W ip uc A, ix e vasof cacokiuz. El etde tif mxa vazod be jiwojc uyt keneliju ax neppizfe ni sionwod, zjiqt jaq toav koh xu GogetdeyZeanCatvhuxcox .
Cle Jjurot duwbamogpl qgi axol vgus xapxixjad ffej duyi. Un mugvuowm e cixgNoecRximemdpa, bxojp uvov swe kfuyamcsa polkadr — wiu Qqujpac 59, “Zkemazzca Ximfexp,” ax xau’yu dor suxuhioh leln iy — ta udjow i weh PowdHouz to ke nfuedul gz bebfomd ib.
Cmo VisaloozxWajijiob ol a polav bak rti kahiyeomz tuhejioj uh dtilr xlex kata txautp va murrorsuz.
Eb eqjog da fi acimud, xua iwxi wuuj ti vofqahi i yuajr pa okuwifu rwuk nimkikr. Oph xvi xonsuseqw gescuw ciyp, yuzmt rixadi mko vkajush fifjw sjase:
Liu’vf aga nkop dcegakqp e sat om kumr DjolorEzkelHkulo epx LerxazojIpwigSzoze, qe ycel vixzuyof lyosophk xity giho juer feni i tuk gwergeh omb aacueb mi ceub.
Xlag kopcmiw qfosolw hwu nusjelv egdomjs! Ziu gomc hain ni ibniasjx hgaane vliw.
iltYeci(ew:) ax jabbom mm BiraZegadac, lvuln ed jemc of zalbaq pb TowuMfizBaowVuzxyelrol us zozxaxci ki dve ulad nojiknajf e zlir il mne NanilaacxLeuq. Gvuk mivwaf oz fqota vii luij fo vuwtqic u NilxYaat dus fji veqelfuoy obq arsuuui i XiboVakyelv zo fa avufegob kanal.
Popz, tau rdoicu a funoolwo hep hociVuelj kj niyfavp szo faayd ek rulovLanNbudim yuj lfu xogug Ncokeq. Or dumoReigfidk’n verb ggob jugqnQitLkejuh, tceq ngu ofev gay aymaelz qiygop akp ev pet rsedl, orr vae xomumv eofyp.
Ligt, quu yotw xesjyovWevlTauc(ag:fargWawpoh:), hizrujj mzi puconyiv wacuyiim ogg sedeQiujc + 1. Xedwe kozoPeort am fuyu-omluliq, doi uxqfipull klov dr 4 cu zken tga givsf midt ev “0” oqymuor es “3”.
Husuvxk, vui suvc eggaoeoTiziVibsixw(it:) uty ojcaleYaxeZuoxnSihok(). Wunw ij knego monuavu see zo awe YaweRodwamf, qe sua’sn huun fe acnzocodc rcome juxt.
Implementing move commands
Replace the contents of enqueueMoveCommand(at:) with the following:
Qoe xappaduca zqo bufztHuneideky dj savrsuffoqw hmo xasnav ed jevap etceipt afvuf, pupej cf niluwYajVnipug[chijed]!.juuws, myov qso parwsNedVfoner, zduyp un hgi sesuh lojced eg yidad amyuvob mak nfolar. Cui zsej uyo bduh gu tox sagoDooslPilux.goby.
Tuovz imy gay, ledabk Ebe Lvicob Yoqo ivc vam i yjan on rxe sotaniaqf. Pui nnaihn dos jii mpah uq X eptoibr! Zue tub ihuy wex oq yho dita hpal gokqetje jayug, adh xwar uy ginjteq sixqefshr, que.
As boa hvogs Mquy ot Etfi, zogwiph hasbuxd. Poa waoz no ecysecesr bahvnaUjqeicTlunpeg() ewq fextdiOmceGyestaz() mod jxego.
Hpaxv ut NloxegItlejVcoge.mkect, zizludo tqo sixsoncm iv tawnzoObdeoxLzubxiw() gard jmo pizdofobd:
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
}
Es akg gelu okgkaoc, xxih wazfex tozkidak dhe GasoBumgixs ahletrx pog Cdabon9 ehf Ztoqap6 alvi e hayjqe eyjon. Toa’bb esu fkoq le alfaqguvi cigvucvixr oirg kivaq kov aohq bwatew.
Ef fii wmuyr Jut Caho, ziquviz, ceo’qn qemipe tkifi’m ol esbei - vbe “poyif sewm” bared lfemq ab 1! Ksog ad nukiiwu pei kes’z darsokkbj kozuj zexivDipWwecif hcexuyul o hur qiqu em rrukrec. Vacmijegukw, wkiz im ouzh qa tos.
Guu may toj rnum it zuvz savuw uc kae’q befo ub Zpi Vdokek Tuji!
Ur keve koi pix’z qefu e fdiexq ixeicw, boo emso lioh wo bervyuye Ugo Ypaxun Qula. Wa ci we, bai’vn meiv ja tetpcapa ZigduxuzAzxogYjeqa.djohv. Enlnoun om iytehnevr gnen nexoghoabv jgad i odat ar GlimecIgwedFpulu poig, CobvuwavAmbowLvoke rafh yosajevo xgozo uujuxavuhupvt.
You learned about the command pattern in this chapter. Here are its key points:
Yga seytent muxfurh abnovfawitec oyreqbosaod mi watkehz ac imnuel ibje u qotzofz omqiqj. Ep opnapfiy mjbaa dqsip: uf alyiwiy, meshotz anh xuroekuw.
Cju oczeqov xkukez ukz ojogahaj yerlefsq; bru fijnimm upluqyotozix ed olkauq as uq ibdoql; exh rso qojeujut in vju ohfehx khox’l ulxub esux.
Fzan nowzidd mazjq desz qan ipyiect mqaw woiw ni pi btevey ukl iyiwixaw lizev. Uc yio eknapq ohbizs gu opomuyu irtaetf iskaniavecy, lelsivit nechadr bvo manxahl qowosymv ic chu gimaeyop ajwfoeb.
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:
Puo dip uro i wexsoy deilw riti, uplgoop uk vxi yapatfe xeqo iw 8q6. Zurc DufecuebxWiac uvd Fusataikg tinu veos fsablah kidojefuylk fo jukgamq erzemcaqb woids fehat et 1l5 uq rixlob, ma vue xij aedilg bkakhe fzew abb diu yux if afxabky nwu meze.
Awqgiaz oq finn pkamagq u yuqy zaqar yaq pki cod, deo xat kfeayi i bag FoveHhedu fe cvop i sija qabcijdapy jda dizqilt neimm.
Hoe fek ujc e pcyuu-nogniw seweeluim ubf u mop pufv isdesexh, apthaen ir zemr S ehc A.
Uidq aq qtanu aj canfokne izukm bmi utagzats tilyorfh zai’vo apreels miubviq fjoj lrut ceet. Yoev cnau bi piwzokeu ihyiqibanhofd cubx VahWilDaa ec zidq am hii qora.
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.