Command Pattern és a pénzügy/számvitel
Most, hogy a mai napi orbitális szívás programozási kihívásokon túlestem, ideje megosztani az infót valami másról, hogy mások is szívjanak annyit, mint én.
A Command tervezési minta egy az adat-vezérelt minták közül és viselkedési minták közé tartozik. Lényege annyi, hogy a kérés egy objektumba van csomagolva, ilyen formában kerül átadásra az ún. invoker objektum karmai közé. Az utána megkeresi az illetékes ojjektumot ami képes ennek a “parancsnak” a teljesítésére és átadja annak, ami ezek után jó katonához híven teljesíti is azt.
Akkor most nézzük meg, hogy is lehet outsource-olni a problémát egy másik fejlesztőnek? Ha már annyit beszélgettünk megrendelésekről Martin papával, akkor most ismét legyen ez a téma.
Tegyük fel, hogy tőzsdézünk. Ennélfogva eladni/venni fogunk, viszont mindkettő egy “megrendelés” lesz. Ennélfogva azokat valamilan módon ebből az osztályból kellene származtatni. Sőt! Mivel a fenti kettő megvalósításának logikája nagyban eltér egymástól (no meg interfészt fogunk typehintelni), ezért interfészként fogjuk definiálni.
[tabs type=”horizontal”][tabs_head][tab_title]PHP[/tab_title][/tabs_head][tab]
1
2
3
4
5
6
7
<?php
interface Order { // a jól szituált megrendelés interfész
public function execute(); // lesz egy végrehajtás metódusa minden megrendelésnek
}
[/tab][/tabs]
Ez lesz a Command pattern-ünk interfésze, viszont nem ártana meg is valósítani mindezt, mint a levegőbe beszélni, nemde? Ahhoz, hogy bármilyen részvényt megvegyünk, nem ártana maga a részvény, nemde? Hozzuk létre ezt, valamint az eladás/vétel “parancsait”:
[tabs type=”horizontal”][tabs_head][tab_title]PHP[/tab_title][/tabs_head][tab]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
class Stock { // a részvényünk, a'la value object. Ezt fogjuk type hintelni, hiszen nem lehet csak úgy mindenféle részvényt megvenni!
private $name = "Letscode"; // nem ártana vállalkozási formát váltanom...
private $quantity = 10; // 10 részvényt kezelünk
public function buy() {
echo $quantity. " darab ". $name . " részvényt megvettek.";
}
public function sell() { // legyen valami bizonyíték is, nemde
echo $quantity. " darab ". $name . " részvényt eladtak.";
}
}
class BuyStock implements Order { // ezzel tudjuk majd jól megvenni a részvényeket
private $stock; // a részvényünket itt tároljuk
public function __construct(Stock $stock) {
$this->stock = $stock; // átadjuk neki a konstruktorban a részvényt, amire vonatkozik
}
public function execute() { // az interfész megkötése
$this->stock->buy(); // a parancs végrehajtásakor megvesszük a részvényt
}
}
class SellStock implements Order { // ezzel tudjuk majd jól eladni a részvényeket
private $stock; // a részvényünket itt tároljuk
public function __construct(Stock $stock) {
$this->stock = $stock; // átadjuk neki a konstruktorban a részvényt, amire vonatkozik
}
public function execute() { // az interfész megkötése
$this->stock->sell(); // a parancs végrehajtásakor eladjuk a részvényt
}
}
[/tab][/tabs]
Most, hogy megvan a részvény, megvan a parancs rá, hogy vegyél, igyál, eladj, nem ártana megkreálni a kis droidot, aki teljesíti a kis parancsainkat!
[tabs type=”horizontal”][tabs_head][tab_title]PHP[/tab_title][/tabs_head][tab]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Broker { // a mi kis brókerünk, aki éhbérért az egekig röpít minket
private $orderList = array(); // a megrendeléseket tartalmazó tömb
public function takeOrder(Order $order) { // itt tudunk neki parancsokat adni
$this->orderList[] = $order; // amiket beleoktrojál a tömbbe
}
public function placeOrders() { // itt pedig elvégzi a feladatot amiért fizetjük
foreach ($this->orderList as $order) { // végigmegyünk az ordereken
$order->execute(); // nem tudjuk, hogy az vétel/adás, viszont azt tudjuk, hogy mivel az Order interfészt implementálta, ezért végrehajtható
}
$this->orderList = array(); // kiűrítjük a listánkat
}
}
// na akkor nézzük hogy is tudjuk munkára fogni a kis minion-unkat!
$stock = new Stock(); // egy jóféle letscode részvény!
$broker = new Broker(); // felveszünk egy új brókert
$broker->takeOrder(new BuyStock($stock)); // adunk neki egy parancsot, miszerint vegyen egy ilyen részvényt
$broker->takeOrder(new SellStock($stock)); // majd eladunk egy ilyet
// megjegyzés: a fentiek még nem kerültek végrehajtásra, szóval ha időközben lelövik a brókerünket, akkor nem vesz semmit
$broker->placeOrders(); // megmondjuk neki, hogy most rögtön végezze el a feladatot
[/tab][/tabs]
A command pattern igen egyszerű minta, mint láthatjuk és ezért nem egy nagy ördöngősség elsajátítani. Segítségével a parancsokat egy végrehajtási sorba tehetjük, megjegyezhetjük azok végrehajtását, visszamondhatjuk, stb. Elválaszthatjuk az objektumot ami kéri az adott feladatot attól ami konkrétan elvégzi és a kettő között egy jól átjárható interfészt hozhatunk létre.