Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > PHP/MySQL > BOOK: Professional PHP Design Patterns
Password Reminder
Register
Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
BOOK: Professional PHP Design Patterns
This is the forum to discuss the Wrox book Professional PHP Design Patterns by Aaron Saray ISBN: 978-0-470-49670-1
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Professional PHP Design Patterns section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developersí questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old June 22nd, 2013, 07:39 AM
Authorized User
Points: 69, Level: 1
Points: 69, Level: 1 Points: 69, Level: 1 Points: 69, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Sep 2012
Location: Indiana, United States
Posts: 13
Thanks: 3
Thanked 1 Time in 1 Post
Default Combining The Factory And Builder Patterns

Thinking about the Builder and Factory patterns, I have had a hard time understanding the differences between the two. From reading this book, the factory pattern seems to return one instance of class from a group of classes that inherits from either from a common abstract class or interface. The factory class determines which class instance to return based upon an incoming parameter. Am I correct on that?

Now a builder class, simply returns a built instance of a class given paramters to build that class. Seems pretty close to what the factory patterns is. So I created some code that attempts to use both of these patterns. Let me know what you think.

I stick to the examples given in the book.

PHP Code:
<?php

interface CDInterface
{
    public function 
setTitle($title);
    public function 
setBand($band);
    public function 
addTrack($track);
}

class 
StandardCD implements CDInterface
{
    public 
$title '';
    public 
$band '';
    public 
$tracks = array();

    public function 
setTitle($title)
    {
        
$this->title $title;
    }

    public function 
setBand($band)
    {
        
$this->band $band;
    }

    public function 
addTrack($track)
    {
        
$this->tracks[] = $track;
    }
}

class 
EnhancedCD implements CDInterface
{
    public 
$title '';
    public 
$band '';
    public 
$tracks = array();

    public function 
__construct()
    {
        
$this->tracks[] = 'DATA TRACK';
    }

    public function 
setTitle($title)
    {
        
$this->title $title;
    }

    public function 
setBand($band)
    {
        
$this->band $band;
    }

    public function 
addTrack($track)
    {
        
$this->tracks[] = $track;
    }
}

interface 
Factory 
{
    public function 
create($type);
}

class 
CDFactory implements Factory
{
    public function 
create($type)
    {
        
$class ucfirst(strtolower($type)) . 'CD';
        return new 
$class;
    }
}

class 
CDBuilder
{
    private 
$factory;

    public function 
__construct(Factory $factory)
    {
        
$this->factory $factory;
    }

    public function 
build($type$title ''$band '', array $tracks = array())
    {
        
$cd $this->factory->create($type);
        
$cd->setTitle($title);
        
$cd->setBand($band);

        foreach (
$tracks as $track) {
            
$cd->addTrack($track);
        }
        return 
$cd;
    }
}

$builder = new CDBuilder(new CDFactory);
$cd $builder->build('Enhanced''Waste Of A Rib''Never Again', array('What It Means''Brrr''Goodbye'));

var_dump($cd);
Reply With Quote
  #2 (permalink)  
Old June 22nd, 2013, 08:18 PM
Wrox Author
Points: 118, Level: 2
Points: 118, Level: 2 Points: 118, Level: 2 Points: 118, Level: 2
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Sep 2009
Location: Milwaukee, WI
Posts: 15
Thanks: 0
Thanked 4 Times in 4 Posts
Default

Hi - you are almost right!

Think about it this way: the factory pattern refers to a method in which the proper instance comes out. The builder is building a class, with potentially unrelated classes/parameters.

Another way to think about it:
In a food plant, a factory pattern will help you create canned vegetable classes. Pass in a type of vegetable ('Green Bean') and you'll get Model_GreenBean back. Pass in 'Peas' and you get Model_Peas - they don't HAVE to be related, but generally they are.
Builder? Well, a builder builds a can of soup. $chickenSoupBuilder->build(); - it creates a broth class, adds a noodles class to the broth class, adds chicken to the broth class, and gives the broth class a label of 'low sodium' - You'll never not get a soup out of it. And you'll never not get a fully created chicken soup from it. Whereas the factory you'll get something different generally based on the input you give it.
__________________
-aaron
--
aaronsaray.com || <-- yeah... try it.
Reply With Quote
The Following User Says Thank You to AaronSaray For This Useful Post:
ericrjones1 (June 26th, 2013)
  #3 (permalink)  
Old June 26th, 2013, 05:21 PM
Authorized User
Points: 69, Level: 1
Points: 69, Level: 1 Points: 69, Level: 1 Points: 69, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Sep 2012
Location: Indiana, United States
Posts: 13
Thanks: 3
Thanked 1 Time in 1 Post
Default

I think I get it now. Rather than say what you did in different ways, I updated my code snippet. My code snippet has the builder class explicitly return a single class and not both StandardCD and EnchancedCD classes.

Coding always helps me to understand more too.

I also show the differences in how a developer would interact with each class. Since the example is pretty simple the difference aren't too great, but I can see how as things become complex the builder pattern that implements factories can be a huge benefit. Especially if you needed to add a new type of CD.

PHP Code:
<?php 

interface CDInterface 

    public function 
setTitle($title); 
    public function 
setBand($band); 
    public function 
addTrack(SongTrack $track); 
}

abstract class 
CD implements CDInterface
{
    public 
$title '';
    public 
$band '';
    public 
$tracks = array();

    public function 
setTitle($title
    { 
        
$this->title $title
    } 

    public function 
setBand($band
    { 
        
$this->band $band
    } 

    public function 
addTrack(SongTrack $track
    {
        
$this->tracks[] = $track->getName(); 
    }
}

// Does not overwrite any CD attributes or methods
class StandardCD extends CD {}

// Overwrites the constructor
class EnhancedCD extends CD
{
    public function 
addDataTrack(DataTrack $track)
    {
        
array_unshift($this->tracks$track->getName());
    }
}

// ----------------------------------------------

interface Track
{
    public function 
getName();
}

class 
SongTrack implements Track
{
    protected 
$name;

    public function 
__construct($name)
    {
        
$this->name $name;
    }

    public function 
getName()
    {
        return 
$this->name;
    }
}

class 
DataTrack implements Track {

    public function 
getName()
    {
        return 
'DATA TRACK';
    }
}

// ----------------------------------------------

interface Factory  

    public function 
create($type); 


class 
CDFactory implements Factory 

    public function 
create($type
    {
        
$class ucfirst(strtolower($type)) . 'CD'
        return new 
$class
    } 
}

// ----------------------------------------------

interface Builder
{
    
// keep the build method uncluddered to enable
    // easier re-use.
    
public function build();
}

abstract class 
CDBuilder implements Builder
{
    protected 
$factory;
    protected 
$band;
    protected 
$title;
    protected 
$tracks;

    public function 
__construct(Factory $factory
    { 
        
$this->factory $factory
    } 

    public function 
build() 
    { 
        
// The class knows what type of CD it wants.
        
$cd $this->factory->create($this->getType()); 
        
$cd->setTitle($this->title); 
        
$cd->setBand($this->band); 

        if (
is_array($this->tracks)) {
            foreach (
$this->tracks as $track) { 
                
$cd->addTrack($track); 
            }
        }
        return 
$cd;
    }

    public function 
band($band)
    {
        
$this->band $band;
    }

    public function 
title($title)
    {
        
$this->title $title;
    }

    public function 
tracks(array $tracks)
    {
        
$this->tracks $tracks;
    }

    
// Returns the appropriate type of CD to produce
    
abstract protected function getType();
}

class 
EnhancedCDBuilder extends CDBuilder
{
    public function 
build()
    {
        
// The class knows what type of CD it wants.
        
$cd $this->factory->create($this->getType()); 
        
$cd->setTitle($this->title); 
        
$cd->setBand($this->band); 

        if (
is_array($this->tracks)) {
            foreach (
$this->tracks as $track) { 
                if (
$track instanceof DataTrack) {
                    
$cd->addDataTrack($track);
                } else {
                    
$cd->addTrack($track);
                } 
            }
        }
        return 
$cd;

    }

    protected function 
getType()
    {
        return 
'Enhanced';
    }
}

class 
StandardCDBuilder extends CDBuilder
{
    protected function 
getType()
    {
        return 
'Standard';
    }
}

// ----------------------------------------------

$factory = new CDFactory;

// ----------------------------------------------

// The factory returns a CD class based upon my
// parameter to the create method.
$emptyEnhancedCD $factory->create('Enhanced');

$emptyEnhancedCD->setTitle('Waste Of A Rib');
$emptyEnhancedCD->setBand('Never Again');

$track_1 = new SongTrack('What It Means');
$track_2 = new SongTrack('Brrr');
$track_3 = new SongTrack('Goodbye');

foreach (array(
$track_1$track_2$track_3) as $track) {
    
$emptyEnhancedCD->addTrack($track);
}

$data_track = new DataTrack;

$emptyEnhancedCD->addDataTrack($data_track);

var_dump($emptyEnhancedCD);

// ----------------------------------------------

// Instantiate the EnchancedCDBuilder and pass in the Factory
// dependency.
$builder = new EnhancedCDBuilder($factory);

// Letting the builder know what attributes I want the
// enhanced CD to to have.
$builder->title('Waste Of A Rib');
$builder->band('Never Again');
$builder->tracks(
    array(
        new 
SongTrack('What It Means'),
        new 
SongTrack('Brrr'),
        new 
SongTrack('Goodbye'),
        new 
DataTrack,
    )
);

// Build it.
// The EnhancedCDBuilder will always return an
// EnhancedCD.
$enhancedCD $builder->build();

var_dump($enhancedCD);

// ----------------------------------------------
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
PHP design pattern (factory?) from Zend Cert crmpicco Beginning PHP 0 July 25th, 2010 02:10 PM
about factory tyc ADO.NET 2 August 29th, 2008 06:53 PM



All times are GMT -4. The time now is 06:33 AM.


Powered by vBulletin®
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.