PHP Academy · Oppitunti

Luontimallit: Factory, Builder, Singleton

Hallitkaa olioiden luontia siististi luontimallien avulla.

Oppitunti 2/413 vaihetta

Luontimallit: Factory, Builder, Singleton on ilmainen PHP Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu PHP Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. PHP Academy-kurssilla on yhteensä 4 oppituntia.

Luonnin hallinta

Luontisuunnittelumallit erottavat toisistaan sen, mitä tarvitsette ja sen, miten se rakennetaan. Kun luonti riippuu ehdoista, koostuu useasta vaiheesta tai se on keskitettävä, new-kutsujen levittäminen ympäri koodikantaa sitoo kutsujat konkreettisiin luokkiin. Tässä käsittelemme tehdasta (ja tehdasmetodia), rakentajaa monimutkaiseen kokoamiseen sekä Singletonia rajoituksineen.

Yksinkertainen tehdas

Yksinkertainen tehdas keskittää luontipäätöksen yhden metodin taakse. Kutsujat pyytävät loogista tyyppiä ja saavat määritetyn konkreettisen instanssin tuntematta luokkien nimiä.

<?php
interface Notifier { public function send(string $msg): string; }
final class EmailNotifier implements Notifier {
    public function send(string $m): string { return "email: $m"; }
}
final class SmsNotifier implements Notifier {
    public function send(string $m): string { return "sms: $m"; }
}

final class NotifierFactory {
    public static function make(string $channel): Notifier {
        return match ($channel) {
            'email' => new EmailNotifier(),
            'sms'   => new SmsNotifier(),
            default => throw new InvalidArgumentException($channel),
        };
    }
}
echo NotifierFactory::make('sms')->send('Hi'), PHP_EOL;

Tehdasmetodi

Tehdasmetodi-malli siirtää instanssien luonnin aliluokille. Perusluokka määrittelee algoritmin, joka kutsuu abstraktia create()-metodia; kukin aliluokka päättää konkreettisen tuotteen. Tämä tukee OCP-periaatetta: uuden luojan voi lisätä muokkaamatta olemassa olevia.

<?php
abstract class ReportExporter {
    abstract protected function create(): string;
    public function export(): string {
        return 'Exported as ' . $this->create();
    }
}
final class PdfExporter extends ReportExporter {
    protected function create(): string { return 'PDF'; }
}
final class CsvExporter extends ReportExporter {
    protected function create(): string { return 'CSV'; }
}
echo (new PdfExporter())->export(), PHP_EOL;
echo (new CsvExporter())->export(), PHP_EOL;

Abstrakti tehdas

Abstrakti tehdas tuottaa toisiinsa liittyvien olioiden tuoteperheitä, joita on käytettävä yhdessä (esimerkiksi MySqlConnection + MySqlQueryBuilder). Se takaa osien yhteensopivuuden, koska yksi tehdas tuottaa koko joukon. Käyttäkää sitä, kun tuoteperheen on säilyttävä sisäisesti yhtenäisenä.

Rakentaja: ongelma

Kun olio tarvitsee monia valinnaisia parametreja, konstruktorit paisuvat vaikeasti luettaviksi paikallisten argumenttien listoiksi tai toisiinsa ketjutettaviksi ylikuormituksiksi, joita PHP:ssä ei edes ole. Rakentaja-malli kokoaa monimutkaisen olion vaihe vaiheelta ja palauttaa lopuksi valmiin, kelvollisen tuotteen.

Ketjutettava rakentaja

Ketjutettava rakentaja palauttaa $this-arvon jokaisesta asetusmetodista, minkä jälkeen build() tuottaa muuttumattoman tuloksen. Näin itse tuote pysyy yksinkertaisena ja kokoamislogiikka siirtyy rakentajaan.

<?php
final class Query {
    public function __construct(public readonly string $sql) {}
}
final class QueryBuilder {
    private string $table = '';
    private array $where = [];
    public function from(string $t): self { $this->table = $t; return $this; }
    public function where(string $c): self { $this->where[] = $c; return $this; }
    public function build(): Query {
        $sql = "SELECT * FROM {$this->table}";
        if ($this->where) { $sql .= ' WHERE ' . implode(' AND ', $this->where); }
        return new Query($sql);
    }
}
echo (new QueryBuilder())->from('users')->where('age > 18')->build()->sql, PHP_EOL;

Rakentaja vai nimetyt konstruktorit

Yksinkertaisemmissa tapauksissa PHP 8:n nimetyt argumentit ja nimetyt konstruktorit (staattiset tehdasmetodit) ovat usein parempi vaihtoehto kuin täysimittainen rakentaja.

  • Käyttäkää nimettyjä argumentteja, kun kaikki tiedot ovat saatavilla kerralla.
  • Käyttäkää rakentajaa, kun kokoaminen tapahtuu useassa vaiheessa, riippuu ehdoista tai sitä käytetään uudelleen useissa kutsukohdissa.
<?php
final class Money {
    private function __construct(public readonly int $cents, public readonly string $cur) {}
    public static function fromDollars(float $d): self {
        return new self((int) round($d * 100), 'USD');
    }
    public static function zero(string $cur = 'USD'): self {
        return new self(0, $cur);
    }
}
var_dump(Money::fromDollars(19.99)->cents); // int(1999)

Singleton

Singleton takaa yhden instanssin ja tarjoaa sille globaalin käyttöpisteen. Toteuttakaa se yksityisellä konstruktorilla ja staattisella käyttömetodilla. Se on aidosti hyödyllinen asioille, joiden on todella oltava ainutlaatuisia prosessin sisällä, mutta samalla se on väärinkäytetyin suunnittelumalli.

<?php
final class Config {
    private static ?self $instance = null;
    private array $data = ['debug' => true];
    private function __construct() {}
    public static function instance(): self {
        return self::$instance ??= new self();
    }
    public function get(string $k): mixed { return $this->data[$k] ?? null; }
}
var_dump(Config::instance()->get('debug'));
var_dump(Config::instance() === Config::instance()); // true

Miksi Singleton aiheuttaa ongelmia

Singletonit tuovat mukanaan piilotetun globaalin tilan: kutsujat hakevat riippuvuuden suoraan Config::instance()-kutsulla sen sijaan, että ilmoittaisivat sen riippuvuudeksi. Tämä heikentää testattavuutta ja rinnakkaisuutta. Nykyaikaisessa PHP:ssä kannattaa rekisteröidä yksi jaettu instanssi DI-konttiin (”yksi instanssi” -elinkaari) ja injektoida se. Näin saatte yhden instanssin ilman globaalia kytkentää.

Oikean työkalun valinta

  • Yksinkertainen tehdas / tehdasmetodi: piilottavat konkreettiset luokat luontipäätöksen taakse.
  • Abstrakti tehdas: tuottaa yhteensopivia tuoteperheitä.
  • Rakentaja: kokoaa monimutkaisia olioita vaihe vaiheelta.
  • Singleton: viimeinen vaihtoehto; suosikaa kontin hallinnoimia jaettuja palveluita.

Kaikki neljä vähentävät riippuvuutta konkreettisista konstruktoreista, mikä helpottaa koodin laajentamista ja testaamista.

Rekisteripohjainen tehdas

Dynaamisempi tehdas hakee luojat rekisteristä, joten uudet tyypit voivat rekisteröityä itse ilman tehtaan muokkaamista (todellinen OCP). Näin laajennusjärjestelmät ja serialisoijat ratkaisevat tyyppinimen konstruktoriksi ajonaikana.

<?php
interface Shape { public function name(): string; }
final class Circle implements Shape { public function name(): string { return 'circle'; } }
final class Square implements Shape { public function name(): string { return 'square'; } }

final class ShapeRegistry {
    private array $creators = [];
    public function register(string $key, callable $factory): void {
        $this->creators[$key] = $factory;
    }
    public function create(string $key): Shape {
        return ($this->creators[$key] ?? throw new InvalidArgumentException($key))();
    }
}
$r = new ShapeRegistry();
$r->register('circle', fn() => new Circle());
$r->register('square', fn() => new Square());
echo $r->create('square')->name(), PHP_EOL; // square

Pikatarkistus

Valitkaa tilanteeseen sopivin luontityökalu.

Kertaus

Hallitsitte olioiden luontia luontisuunnittelumalleilla: tehtaat piilottavat konkreettiset tyypit ja valitsevat tuoteperheet, rakentajat kokoavat monimutkaisia olioita ketjutettavasti, ja Singletonilla on omat hyötynsä ja haittansa. Nykyaikainen johtopäätös on tämä: käyttäkää tehtaita ja rakentajia vapaasti, mutta korvatkaa Singleton DI-kontin jaetun instanssin elinkaarella, jotta riippuvuudet pysyvät eksplisiittisinä ja testattavina.

Aloita maksutta

Opi PHP tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
49
Oppitunnit
195

Usein kysytyt kysymykset

Onko oppitunti ”Luontimallit: Factory, Builder, Singleton” ilmainen?

Kyllä – oppitunnin ”Luontimallit: Factory, Builder, Singleton” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko PHP Academy-kurssin, päivitä CoddyKit PROhon. PHP Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Luontimallit: Factory, Builder, Singleton”?

Hallitkaa olioiden luontia siististi luontimallien avulla. Harjoittelet PHP Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni PHP Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin PHP Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Luontimallit: Factory, Builder, Singleton”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä PHP Academy-oppitunnilla?

Kyllä. Jokainen PHP Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. SOLID-periaatteet käytännössä
  2. Luontimallit: Factory, Builder, Singleton
  3. Rakennemallit: Adapter, Decorator, Facade
  4. Käyttäytymismallit: Strategy, Observer, Command
← Takaisin: PHP Academy