views:

125

answers:

1

My Room class has a lot of methods I used before I decided to use the command pattern. Previously, I was invoking a lot of commands and now it seems I have to make a method in my roomParser class for every method. If I wanted to invoke say, setHotelCode I would have to create a method in roomParser that iterates through and invokes the method. Is this the way I should be using the command pattern?

<?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='' ) { }

    public function setHotelCode($code ) { $this->_hotelCode = $code; }

    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;

Edit: I'm thinking it may be easier if I made the RoomParser less generic by storing properties that all the objects will share. Though I'll probably have to make methods if I want to override for a certain object.

+1  A: 

This class looks like it is doing at least three different things? (Storing room booking data, creating SOAP packets, handling SOAP transport). Your parse() function is a bit of a mystery...

What if you created a simpler Room class?

class Room
{
  protected $_properties = array( 'numberOfAdults' => 0, 'numberOfKids' => 0, ... etc );

  function __set( $name, $value )
  {
     if (!isset($this->_properties[$name])) throw new Exception( 'Invalid property ' . $name );
     $this->_properties[$name] = $value;
  }

  ... etc ...
}
Steve