2015-11-16 14 views
6

Próbuję stworzyć bota dla komunikatora Telegram, próbując poznać OOP. Naprawdę zagubiłem się, jak podejść do problemu. Mam jednostkę wiadomości, ze wszystkimi pobierającymi i ustawiającymi, to myślę, że jest to dość proste. Mój problem jest, że chcę, aby utworzyć dwie (lub więcej) rodzajów fabrykNiepewność implementacji wzorów fabrycznych

1)proste przesłanie gdzie po prostu karmić fabrykę z chat_id chcesz wysłać wiadomość i tekst, które mogłyby być coś takiego:

<?php 

namespace Telegram\Domain\Factory; 

use Telegram\Domain\Entity\Message; 

class MessageRaw extends MessageAbstract { 
    public function createMessage($chat_id, $text) { 
     $message = new Message(); 
     $message->setChatId($chat_id); 
     $message->setText($text); 

     return $message; 
    } 
} 

gdzie MessageAbstract jest

<?php 

namespace Telegram\Domain\Factory; 

abstract class MessageAbstract { 
    abstract public function createMessage($chat_id, $text); 
} 

2)wiadomość z klawiaturą (Telegram umożliwia dołączenie niestandardowej klawiatury podczas wysyłania wiadomości). Mam tutaj problem, klawiatura jest podana jako tablica, więc byłby to jeszcze jeden argument do createMessage.

Więc moim problemem jest, czy zawsze powinienem podać argument klawiaturowy $, czy jest to prosta wiadomość, czy komunikat z klawiaturą? Czy te dwa rodzaje wiadomości są na tyle różne, że powinny być tworzone z różnych klas (chyba nie)? A może nie powinienem tego robić w fabryce, ale z setterami i getterami?

TLDR: Jak utworzyć obiekt z różną liczbą argumentów w fantazyjny sposób, coś w tym

$MessageRaw = new MessageRaw($chat_id, $text); 
$MessageNumericKeyboard = new MessageNumericKeyboard($chat_id, $text); //numeric keyboard is standard so can be set in the createMessage Function 
$MessageCustomKeyboard = new MessageCustomKeyboard($chat_id, $text, ['A', 'B']); //should it be done like this? 
+0

Nie widzę tutaj zastosowania dla '' MessageRaw'', dlaczego nie użyjesz bezpośrednio '' Message''? W każdym razie, jeśli nalegasz na używanie tego, spróbuj zawsze wysłać cały obiekt, co oznacza, że ​​wysyłasz '' nową wiadomość() '' zamiast $ chat_id, $ text (najpierw pozwoliłoby to na wpisanie zmiennej, a drugie to daje dostęp do wszystkich dostępnych metod na tym obiekcie). – ahmad

+0

@ahmad Przepraszam, nie podążam za tobą. Po prostu ustawiam obiekt, nic nie wysyłam (jeszcze). Później wyślę to, ale chcę ustawić klawiaturę (jeśli to konieczne) w miły sposób i nie wiem, czy to musi być zrobione podczas tworzenia obiektu. – godsaway

+0

Ahmad odnosi się do Dependency Injection: http: // code .tutsplus.com/tutoriale/dependency-injection-in-php - net-28146 – CD001

Odpowiedz

4

Zgadzam się z @ Znaki CD001 dotyczące podtypy/rozszerzenie, więc nie będę powtarzać jego odpowiedź, ale nadal można użyć wzoru fabrycznego poprzez określenie wymaganego typu użyciu iniekcji zależność i zwrócenie odpowiedniego obiektu.

Możesz podać dedykowany parametr dla tej zależności na metodzie fabrycznej, lub możesz użyć metody przeciążania, aby wstrzyknąć i sprawdzić tylko te konkretne typy (jeśli istnieją dodatkowe klasy, które mogą być zwrócone poza dwoma wskazanymi).

Przyklejenie z fabrycznym wzorem naprawdę pomoże rozwinąć to w dół drogi bez zbytniej dodatkowej pracy, cięcie narożników teraz doprowadzi tylko do bólu później.


EDIT:

wtryskowa(nb: podaję typu param, aby pokryć jedną możliwą technikę ekspansji poprzez ciąg, ale może to równie dobrze być wstrzykiwany jako typ obiektu Uwzględniono także opcję wstrzykiwania atrybutów wiadomości w tym samym czasie dla konstruktora wiadomości, dzięki czemu można odzyskać w pełni utworzony obiekt zamiast pustego DTO)

class MessageFactory { 
    public static function get($type,$attributes=NULL,$keyboard=NULL) { 
     if ($keyboard && !($keyboard instanceof MessageKeyboardInterface)) { 
      // ... trigger some exception here 
     } elseif (!$keyboard) { 
      $keyboard = new BasicKeyboard(); 
     } 
     switch($type): 
     case('standard'): 
      return new StandardMessage($attributes,$keyboard); 
      break; 
     case('short'): 
      return new ShortMessage($attributes,$keyboard); 
      break; 
     case('long'): 
      return new LongMessage($attributes,$keyboard); 
      break; 
     endswitch; 
    } 
} 

W ten sposób wszystkie obiekty Message mogą korzystać z tego samego interfejsu, mogą korzystać z niestandardowych lub podstawowych klawiatur i można je łatwo rozszerzyć.Możesz oczywiście rozszerzyć atrybuty $ i użyć swoich indywidualnych ustawiaczy po utworzeniu instancji lub pętli nad nimi w konstruktorze, jeśli masz ich wiele. Osobiście nie lubię mnóstwa parametrów w contruructor i wolałbym przechodzić przez tablicę opcjonalnych parametrów.

+0

OK, wydaje mi się to właściwą odpowiedzią, ponieważ chcę używać fabryk i myślę, że pasuje ona do tej sytuacji. Nadszedł czas, aby włączyć cały tekst do kodu, ale w ten sposób uczymy się, prawda? – godsaway

+0

Dziękuję, z tą edycją wszystko jest jasne – godsaway

+0

@godsaway Płacę to naprzód :) – oucil

2

To wygląda lepiej pasuje do wspólnym lub w ogrodzie sub-typowania zamiast przy użyciu wzór fabryki, na przykład:

class Message { 

    // e.g. 
    protected $chatId; 
    protected $text; 

    // constructor 
    public function __construct($chatId, $text) { 
     $this->setChatId($chatId); 
     $this->setText($text); 
    } 

    // ... stuff 
} 

final class MessageCustomKeyboard extends Message { 

    // e.g. 
    private $_keyboard; 

    // constructor overrides parent 
    public function __construct($chatId, $text, array $keyboard) { 
     parent::__construct($chatId, $text); 
     $this->setKeyboard($keyboard); 
    } 

    // ... stuff 
} 

$message = new Message(1, "Hello World"); 
$messageCustomKeybaord = new MessageCustomKeyboard(2, "Hello again", array("a", "b")); 
Powiązane problemy