Как мне провести рефакторинг моего класса? - PullRequest
0 голосов
/ 11 февраля 2010

В основном у меня есть класс, который отправляет SOAP-запрос на информацию о комнате, получает ответ, он может обрабатывать только одну комнату за раз .. например:

class roomParser {
    private $numRooms;
    private $adults;
    private $dailyPrice;

    public function parse(){}
    public function send(){}

};

$room = new roomParser( $arrival, $departue );
$return = $room->parse();

if ( $return ) { }

Теперь у меня возникла дилемма, состоящая в основном в поддержке нескольких комнат, и для каждой комнаты я должен отдельно хранить информацию о суточной цене, # о количестве взрослых, так что мне приходится сессионизировать информацию о каждой комнате, так как она имеет форму многошаговой формы.

Должен ли я просто создать несколько экземпляров своего объекта или каким-либо образом изменить свой класс, чтобы он поддерживал любое количество комнат в массиве комнат, а в массиве комнат он содержит свойства для каждой комнаты?

Редактировать # 1: После получения совета я попытался реализовать шаблон Command:

<?php

interface Parseable {

    public function parse( $arr, $dept );
}

class Room implements Parseable {

    protected $_adults;
    protected $_kids;
    protected $_startDate;
    protected $_endDate;
    protected $_hotelCode;
    protected $_sessionNs;
    protected $_minRate;
    protected $_maxRate;
    protected $_groupCode;
    protected $_rateCode;
    protected $_promoCode;
    protected $_confCode;
    protected $_currency = 'USD';
    protected $_soapAction;
    protected $_soapHeaders;
    protected $_soapServer;
    protected $_responseXml;
    protected $_requestXml;

    public function __construct( $startdate,$enddate,$rooms=1,$adults=2,$kids=0 ) {
        $this->setNamespace(SESSION_NAME);
        $this->verifyDates( $startdate, $enddate );

        $this->_rooms= $rooms;
        $this->_adults= $adults;
        $this->_kids= $kids;

        $this->setSoapAction();
        $this->setRates();
    }

    public function parse( $arr, $dept ) {
        $this->_price = $arr * $dept * rand();
        return $this;
    }

    public function setNamespace( $namespace ) {
        $this->_sessionNs = $namespace;
    }

    private function verifyDates( $startdate, $enddate ) {}

    public function setSoapAction( $str= 'CheckAvailability' ) {
        $this->_soapAction = $str;
    }

    public function setRates( $rates='' ) { }

    private function getSoapHeader() {
        return '<?xml version="1.0" encoding="utf-8"?>
            <soap:Header>
            </soap:Header>';
    }

    private function getSoapFooter() {
        return '</soap:Envelope>';
    }

    private function getSource() {
        return '<POS>
            <Source><RequestorId ID="" ID_Context="" /></Source>
            </POS>';
    }

    function requestXml() {
        $this->_requestXml  = $this->getSoapHeader();
        $this->_requestXml .='<soap:Body></soap:Body>';
        return $this->_requestXml;
    }

    private function setSoapHeaders ($contentLength) {
        $this->_soapHeaders = array('POST /url HTTP/1.1',
            'Host: '.SOAP_HOST,
            'Content-Type: text/xml; charset=utf-8',
            'Content-Length: '.$contentLength);
    }
}

class RoomParser extends SplObjectStorage {

    public function attach( Parseable $obj ) {
        parent::attach( $obj );
    }

    public function parseRooms( $arr, $dept ) {
        for ( $this->rewind(); $this->valid(); $this->next() ) {
            $ret = $this->current()->parse( $arr, $dept );
            echo $ret->getPrice(), PHP_EOL;
        }
    }
}

$arrive = '12/28/2010';
$depart = '01/02/2011';
$rooms = new RoomParser( $arrive, $depart);
$rooms->attach( new Room( '12/28/2010', '01/02/2011') );
$rooms->attach( new Room( '12/29/2010', '01/04/2011') );
echo $rooms->count(), ' Rooms', PHP_EOL;

Ответы [ 3 ]

3 голосов
/ 11 февраля 2010

Хорошо, что вы определили как объект, который обрабатывает одну комнату, так что, естественно, если вы хотите обрабатывать несколько комнат, вы должны создать объект, который является просто коллекцией этих объектов с одной комнатой.

Если вы намереваетесь взаимодействовать с MultiRoomParser так же, как и с RoomParsers, этот сценарий может стать хорошим кандидатом для Composite Pattern . По сути, ваш MultiRoomParser будет содержать коллекцию RoomParsers, и когда вы вызываете такой метод, как parse () для вашего MultiRoomParser, он просто перебирает все RoomParsers в своей коллекции и вызывает parse () для каждого элемента.

1 голос
/ 11 февраля 2010

Исходя из информации в вопросе, я бы, вероятно, использовал Шаблон команды

Все комнаты должны реализовывать команду parse ()

interface Parseable
{
    public function parse($arr, $dept);
}

Экземпляр комнаты может выглядеть следующим образом

class Room implements Parseable
{
    protected $_price;
    protected $_adults;
    public function parse($arr, $dept) {
         // nonsense calculation, exchange with your parse logic
        $this->_price = $arr * $dept * rand();
        return $this;
    }
    public function getPrice()
    {
        return $this->_price;
    }
}

Чтобы просмотреть их, я бы добавил их в Invoker, который хранит все комнаты и знает, как вызвать их метод parse (), а также знает, что делать с возвратом из parse (), если необходимо

class RoomParser extends SplObjectStorage
{
    // makes sure we only have objects implementing parse() in store      
    public function attach(Parseable $obj)
    {
        parent::attach($obj);
    }

    // invoking all parse() methods in Rooms
    public function parseRooms($arr, $dept)
    {
        for($this->rewind(); $this->valid(); $this->next()) {
            $ret = $this->current()->parse($arr, $dept);
            // do something with $ret
            echo $ret->getPrice(), PHP_EOL;
        }
    }
    // other methods
}

И тогда вы можете использовать это так:

$parser = new RoomParser;
$parser->attach(new Room);
$parser->attach(new Room);
$parser->attach(new Room);
$parser->attach(new Room);
echo $parser->count(), ' Rooms', PHP_EOL;

$parser->parseRooms(1,2);

Обратите внимание, что Invoker расширяет SplObjectStorage, поэтому он реализует Countable, Iterator, Traversable, Serializable и ArrayAccess.

0 голосов
/ 11 февраля 2010

Я бы сказал, что создание нескольких экземпляров объекта имеет смысл. Так работают объекты.

...