I want to know if this tutorial is correctly implementing factory design pattern in PHP. Below is the actual source code.
<?php
class Automobile
{
private $vehicle_make;
private $vehicle_model;
public function __construct($make, $model)
{
$this->vehicle_make = $make;
$this->vehicle_model = $model;
}
public function get_make_and_model()
{
return $this->vehicle_make . ' ' . $this->vehicle_model;
}
}
class AutomobileFactory
{
public static function create($make, $model)
{
return new Automobile($make, $model);
}
}
// have the factory create the Automobile object
$veyron = AutomobileFactory::create('Bugatti', 'Veyron');
print_r($veyron->get_make_and_model()); // outputs "Bugatti Veyron"
According to a book "Design Patterns" by Gang of Four, applicability of factory pattern is
a class can't anticipate the class of objects it must create
a class wants its subclasses to specify the objects it creates
classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
First point, this example actually knows what class of objects to create, which is Automobile, doesn't it?
Second point, there is no subclass. Automobile class does not inherit from AutomobileFactory. I thought AutomobileFactory should have at least one function implemented by Automobile, which deals with object creations.
Can someone clarify this? I just started learning design patterns, and every time I encounter tutorials different from others, it confuses me a lot.
I pretty much agree with what is said in Wikipedia
The creation of an object precludes its reuse without significant duplication of code.
The creation of an object requires access to information or resources that should not be contained within the composing class.
The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.
The main reason I create factories is this one I highlighted.
For example, let's imagine a real world factory with many plants throughout the country. This factory produces doors. Doors needs knobs. For logistics reasons, each one of the plants of the factory has its own knob suppliers, another completely different factory.
The production manager software of this factory will choose based on some criteria which plant will produce a lot of doors, but it does not need to know from where the knobs will come. The chosen plant will ask for its own supplier for a knob for the produced door.
However, for the client, it does not matter which plant made the door, he only cares about having his door.
Let's put this on code:
class Knob {
// something...
}
interface KnobSupplier {
public function makeKnob();
}
class SaoPauloKnobSupplier {
public function makeKnob() {
return new Knob('Knob made in São Paulo');
}
}
class NewYorkKnobSupplier {
public function makeKnob() {
return new Knob('Knob made in New York');
}
}
class Door {
public function __construct(Knob $knob) {
// something...
}
}
interface DoorFactory {
public function makeDoor();
}
class SaoPauloDoorFactory {
private $knobSupplier;
public function __construct() {
$this->knobSupplier = new SaoPauloKnobSupplier();
}
public function makeDoor() {
return new Door($this->knobSupplier->makeKnob(), "Door made in São Paulo");
}
}
class NewYorkDoorFactory {
private $knobSupplier;
public function __construct() {
$this->knobSupplier = new NewYorkKnobSupplier();
}
public function makeDoor() {
return new Door($this->knobSupplier->makeKnob(), "Door made in New York");
}
}
class ProductionManager {
private $plants = array();
// methods for adding plants, etc...
public function getDoor() {
// Somehow decides which plant will create the door.
return $plant->makeDoor();
}
}
class Client {
public function getMyDoor(ProductionManager $manager) {
return $manager->getDoor();
}
}
Using this code like:
$manager = new ProductManager();
$manager->addPlant(new SaoPauloDoorFactory());
$manager->addPlant(new NewYorkDoorFactory());
$client = new Client();
var_dump($client->getMyDoor($manager));
ProductManager does not know anything about knobs, Client does not know anything about the factory having more than one plant.
I don't really like the tutorial. As you can see in the WikiPedia page about factories ( https://en.wikipedia.org/wiki/Factory_pattern ) - it's normally done differently. The WikiPedia example does comply with the rules you mention. Check out the PHP section there.
I'm with you kidonchu, I don't really see that example as a traditional factory method pattern.
I would write your example like this (psuedo code)
<?php
abstract class CarAbstract
{
protected $_vehicleMake;
protected $_vehicleModel;
public function __construct($model)
{
$this->_vehicleModel = $model;
}
public function getMakeAndModel()
{
return $this->_vehicleMake . ' ' . $this->_vehicleModel;
}
}
class Bugatti extends CarAbstract
{
public function __construct($model)
{
parent::__construct($model);
$this->_vehicleMake = get_class($this);
}
}
class AutomobileFactory
{
public static function getInstance($make, $model)
{
if (is_file('Model/Car/' . $make . '.php')){
require_once 'Model/Car/' . $make . '.php';
$car = new $make($model);
}else{
throw new Exception('Car not found');
}
}
}
$veyron = AutomobileFactory::getInstance('Bugatti', 'Veyron');
print_r($veyron->getMakeAndModel()); // outputs "Bugatti Veyron"
There's actually a single Factory Method design pattern following the original gang of four catalog. The Abstract Factory is wholly different and is based on different structural assumptions. The Simple Factory is not a design pattern, but the what Freemans call a 'programming idiom.' The Factory method includes an abstract Creator and Product, and the Clients generally make their requests through the Creator. Specific factories are found in the ConcreteCreator(s) and the concrete products are child classes of the Product class and are instantiated by concrete creators. For a complete and simple PHP example see http://www.php5dp.com/a-simple-php-design-pattern-the-factory-method/.
Related
First of all sorry for not explaining this correctly I have hard time finding my words.
I been following a laracast php tutorial about The Decorator Pattern. It explain how you can build up an object at run time.
From the tutorial
interface CarService{
public function getCost();
}
class Service implements CarService {
public function getCost()
{
return 20;
}
}
class OilChange implements CarService{
protected $carService;
public function __construct(CarService $carService)
{
$this->carService = $carService;
}
public function getCost()
{
return 10 + $this->carService->getCost();
}
}
class Tyre implements CarService {
protected $carService;
public function __construct(CarService $carService)
{
$this->carService = $carService;
}
public function getCost()
{
return 20 + $this->carService->getCost();
}
}
The main bit im focus on is this
$carService = new Tyre(new OilChange(new Service()));
echo $carService->getCost();
//output 50
As the tutorial describes having this code helps minimize repetition of code in the classes by introducing an interface. I understand why its a good approach but there is a bit that wasnt explained in the tutorial. if you have 100 types of services there is a possibility of 10,000 different class initiation such as this one $carService = new Tyre(new OilChange(new Service())); or this one $carService = new OilChange(new Service());
As you can see this will quickly add up if you have to initiate classes base on each possible outcome of car service (10,000).
how could I solve this so that it knows exactly what class/type of service to initialize? clearly having a long if statement for every single condition which would be 10,000 is not correct.
So I have understood how interfaces and abstraction work in PHP, I just don't see the point for example, of having a interface if it just sets a guide and requires implemented objects to have certain methods. Especially since the interface is not even getting instantiated.
This also goes with abstraction, I just can't apply it to my code and see it as such a great thing. When I am trying to create objects on a bigger scale to interact with each other in order to figure out interfaces, each class ends up passing information back and forth, but never is the interface touched.
So what I'm asking is if you guys have any advice or links to outside sources that is good at explaining this kind of thing.
Here's one simple example. Creating interfaces and abstract classes allows you to ensure an object adhears to a common API. See the example below.
interface iCar
{
function drive();
}
abstract class Car implements iCar
{
public $make = 'Generic';
public function drive()
{
printf("I'm driving in my %s%s", $this->make, PHP_EOL);
}
}
class FordTruck extends Car
{
public $make = "Ford";
}
class Porsche extends Car
{
public $make = 'Porsche';
public function drive()
{
printf("I'm speeding around in my %s%s", $this->make, PHP_EOL);
}
}
class Yugo extends Car
{
public $make = 'Yugo';
public function drive()
{
printf("I'm pushing my %s around town%s", $this->make, PHP_EOL);
}
}
function drive(iCar $car)
{
$car->drive();
}
$car1 = new FordTruck;
$car2 = new Porsche;
$car3 = new Yugo;
drive($car1);
drive($car2);
drive($car3);
Even if you don't specify the type of input parameter on the drive() function, you can check if the input is an instanceof an iCar
function drive($car)
{
if ($car instanceof iCar)
$car->drive();
}
Another example would be building a caching interface in your application. You can specify that all cache engines support the same methods for reading/writing/invalidating objects in the cache without knowing (or caring) about the actual implementation of a particular cache engine.
I could give you the simplest as possible example.
Assume you want a feature that allow your site to login with Facebook/Twitter
# here's your interface/abstract class
interface Auth_Adapter {
public function auth();
}
# now your Facebook
class Auth_Adapter_Facebook implements Auth_Adapter {
public function login() {
# include facebook-sdk and auth
}
}
# Twitter
class Auth_Adapter_Twitter implements Auth_Adapter {
public function login() {
# include twitter-oauth and auth
}
}
Imagine when someone try to use Facebook/Twitter thing They can simply call
$adapter = new Auth_Adapter_Facebook;
$adapter->login();
$adapter = new Auth_Adapter_Twitter;
$adapter->login();
As you can see both adapters use the same login interface. What's happen if in the future you have to include 'Pinterest' login? Your code still work as long as you implement the same interface.
EDIT: More explanations
Here's the reason why you have to use interface or abstract
# I use `type-hinting` here. So I can ensure that only object that implements `Auth_Adapter` will allow. Without this implementation someone might pass some other object that doesn't have `login` method in. But in our case we don't have to worry about that.
public function perform_login(Auth_Adapter $adapter) {
$adapter->login();
}
I a unit-testing beginner and seem to be stuck on how to unit test a function that contains an internal function call. For example, testing the following:
public function getBlueFooCount($fooId) {
$foo = $fooDao->getFoosById($fooId);
// custom logic to pull out the blue foos from result set
// custom count business logic on blue foos ...
return $count;
}
How would I be able to mock what the internal function retrieves? Is this because the function is too tightly coupled and it needs to be loosened?
To build off #aib's answer, when we started to unit test our legacy code base the majority of our classes were very tightly coupled and many methods were instantiating new objects themselves. While we've taken steps on implementing Dependency Injection and Inversion of Control going forward, we were still stuck with hundreds of classes that still needed unit tested.
When writing a unit test for a legacy method, we refactored and pulled the instantiation out into a new small method we could then stub. Not the best pattern, but it was cheap and got the job done without having to do a larger refactoring.
class FooCounter {
public function getFooDao(){
return new FooDao();
}
public function getBlueFooCount($fooId) {
/* was this
$fooDao = new FooDao();
*/
$foo = $this->getFooDao()->getFoosById($fooId);
// custom logic to pull out the blue foos from result set
// custom count business logic on blue foos ...
return $count;
}
}
class FooCounterTest extends PHPUnit_Framework_TestCase {
public function test_getBlueFooCount(){
$fooCounter = $this->getMock('FooCounter', array('getFooDao'));
$fooCounter->expects($this->any())
->method('getFooDao')
->will($this->returnValue(new MockFooDao()));
$this->assertEquals(0, $fooCounter->getBlueFooCount(1));
}
}
If we were implementing a new class, we typically are using constructor based DI and it is the answer I will give if you are creating something new. Here's a link by someone else because I trust it's been said better before (sort of DRY): Dependency Injection and Unit Testing. And some examples of each for your case:
Constructor based injection
class FooCounter {
private $_fooDao
public function __construct($fooDao){
$this->_fooDao = $fooDao
}
public function getBlueFooCount($fooId) {
$foo = $this->_fooDao->getFoosById($fooId);
// custom logic to pull out the blue foos from result set
// custom count business logic on blue foos ...
return $count;
}
}
class FooCounterTest extends PHPUnit_Framework_TestCase {
public function test_getBlueFooCount(){
$fooCounter = new FooCounter(new MockFooDao());
$this->assertEquals(0, $fooCounter->getBlueFooCount(1));
}
}
Setter based injection
class FooCounter {
private $_fooDao
public function setFooDao($fooDao){
$this->_fooDao = $fooDao
}
public function getBlueFooCount($fooId) {
$foo = $this->_fooDao->getFoosById($fooId);
// custom logic to pull out the blue foos from result set
// custom count business logic on blue foos ...
return $count;
}
}
class FooCounterTest extends PHPUnit_Framework_TestCase {
public function test_getBlueFooCount(){
$fooCounter = new FooCounter();
$fooCounter->setFooDao(new MockFooDao());
$this->assertEquals(0, $fooCounter->getBlueFooCount(1));
}
}
You need to mock $fooDao. Hopefully there's a setter or a DI container and you're not creating it with new (in which case it might be too tightly coupled.)
I'm wondering if anyone could give me a suggestion for to best handle this situation:
I have several systems from which to pull data to display on a single PHP-driven website. The type of information will be the same across systems (contacts, addresses, etc) but the way I pull data (MS-SQL, XML, REST) will not.
I want to create a class, or set of classes, for each of the connection types and use simple methods such as getContact(), getAddress(), etc. I am wondering how best to structure this.
The most obvious way that comes to mind means creating classes for each connection type, like:
class.sys_mysql.php. class.sys_xml.php, etc
But then won't I be duplicating the methods in each class? Maybe that's OK, but I'm curious if there's a better way, as far as future maintenance goes.
Maybe I should simply isolate the queries/data extraction methods, into separate class files? Classes within classes? Extended classes? I'm less familiar with these.
Any advice would be greatly appreciated.
DC
--------- more info ----------
Hi all. I really appreciate all the great advice. Not to belabor this thread but I'm still a bit confused on how I should break things down. I will try and be a bit more specific:
Basically, I have 3 (more in the future) offices, from which one PHP website pulls information. Each office uses a different CRM, and a different system for interfacing with that CRM. One uses MSSQL, another XML requests, etc.
Each office wants to display information similarly on the website, but there are minor differences. There may be more differences in the future. However, there are by far more similarities, and so I want to capitalize on higher level functions like getContacts($id) which are shared between them.
I am trying to write these classes so I can:
1) use higher level methods to pull data easily
2) account for different ways of pulling data (xml,sql,etc)
3) account for differences between how data is displayed on the website (office 1, office 2, office 3)
4) manage the connection credentials for each office and allow for expandability_
5) I should also mention that I will be creating separate classes for reporting, sending out automated e-mails, calculating finances...separate modules that will need to use existing classes to pull data.
I realize that some of the examples here see to cover 1 and 2, but I am confused as to how to get 3, 4 and 5 working with 1 and 2.
I really appreciate the help.
DC
This is what Interfaces are for.
You define the methods required to interact with the data in an Interface, and then you create classes that implement that Interface
If some of the systems have similar access models (i.e. perhaps two different DB Servers, but both are accessed using PDO) you could abstract it further and put the "low level" functionality into service-specific classes (which implement an Interface) and then a higher-level class which defines the actual methods you use.
Another option is that you could put the "common" methods (those that are identical or can be made idetntical with service-type checks) into a base class, which all others extend.
Example for option one:
interface DataModel {
public function findContacts($search);
public function getContact($id);
public function findAddresses($search);
public function getAddress($id);
}
class XMLDataModel implements DataModel {
public function findContacts($search) {
...
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
class RESTDataModel implements DataModel {
public function findContacts($search) {
...
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
As you can see, you simply define an Interface, which specifies which methods a class must implement.
If you had two very similar classes, perhaps one for MySQL and one for PostreSQL, and you can't/don't want to combine them into a single PDO class, you could do the following:
class PDODataModel implements DataModel {
private $model;
public function __construct ($serverType) {
if ($serverType === 'mysql') {
$this->model = new MySQLPDODataModel();
}
elseif ($serverType === 'postgresql') {
$this->model = new PostgresQLPDODataModel();
}
}
public function findContacts($search) {
// common logic about $search, perhaps checking it's a valid search?
$result = $this->model->searchForContacts($search);
// more common logic, maybe higher level filtering..
return $result;
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
interface PDODataModelDriver {
public function searchForContacts($search);
}
class MySQLPDODataModel extends PDODataModel implements PDODataModelDriver {
public function searchForContacts($search) {
// MySQL-specific query to search for contacts
}
}
class PostgresSQLPDODataModel extends PDODataModel implements PDODataModelDriver {
public function searchForContacts($search) {
// PostgreSQL-specific query to search for contacts
}
}
The other option I mentioned was to work in the opposite direction:
abstract class PDODataModel implements DataModel {
protected $pdo;
protected $dsn;
public function __construct () {
$this->pdo = new PDO($this->dsn);
}
public function findContacts($search) {
// common logic about $search, perhaps checking it's a valid search?
$result = $this->searchForContacts($search);
// more common logic, maybe higher level filtering..
return $result;
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
class MySQLPDODataModel extends PDODataModel {
protected $dsn = 'mysql:dbname=testdb;host=127.0.0.1';
protected function searchForContacts($search) {
// MySQL-specific query to search for contacts
}
}
class PostgresSQLPDODataModel extends PDODataModel {
protected $dsn = 'pgsql:host=localhost;port=5432;dbname=testdb';
protected function searchForContacts($search) {
// PostgreSQL-specific query to search for contacts
}
}
This is a classical example of a strategy design patter. Your first mind was absolutely fine, but if you're repeating yourself in each class you should consider creation of a abstract class that will handle the common code.
So it could look like this:
$myService = new MyService(new XMLReader('/path/to/file'));
echo $myService->getContanct('abc')->getName();
And skeleton of your classes:
class MyService {
private $reader;
public function __construct(ReaderInterface $reader) {
$this->reader = $reader;
}
// ...
public function getContacnt($id) {
$contact = $this->reader->getContact($id);
// do some extra stuff here
return $contact;
}
}
interface ReaderInterface {
public function getContanct($id);
public function getAddress($id);
}
abstract class AbstractReader implements ReaderInterface {
protected $loaded = false;
protected $data = array();
abstract protected function load();
public function getContanct($id) {
if ($this->loaded == false) {
$this->load();
$this->loaded = true;
}
return $this->data['contact'][$id];
}
}
class XMLReader extends AbstractReader {
public function __construct($filepath) {
...
}
protected function load() {
...
foreach (...) {
$this->data[...] = ...;
}
}
}
class MSSQLReader extends AbstractReader {
public function __construct(PDO $dbh) {
...
}
protected function load() {
...
while ($row = $stmt->fetchRow()) {
$this->data[...] = ...;
}
}
}
EDIT (2011-03-07) - According to your comment.
PHP supports variable variables (new $type()) but never use this! It's a horrible, and if overused make code really crappy.
This is a yet another example of a "classical issue". Use a factory pattern (depending on the complexion of the creation you might want to use more abstract variety of this pattern - abstract factory
When you need to dynamically determine class name (eg. from variable) use reflection API to instate an object.
You should create an object-storage mapping layer for each data source, which instantiates the objects into storage agnostic model objects. See http://martinfowler.com/eaaCatalog/dataMapper.html
If you have control over the structure of your data formats, I suggest you serialize your data in a consistent way (especially in XML) and provide drivers for each data format.
For instance, every driver will have 'findAll', 'getOne', 'count', etc. methods. The driver can be given a model to populate with the retrieved data.
abstract class DataDriver {
function __construct($model) {}
abstract public function findAll();
abstract public function getOne();
abstract public function count();
// ...
}
class XMLDriver extends DataDriver {
// implements all the methods
}
class SQLDriver extends DataDriver {
// implements all the methods
}
class Contact {
public var $firstName;
public var $lastName;
function getFullName() {
return trim($this->firstName . ' ' . $this->lastName);
}
}
$accessor = new SQLDriver('Contact');
$contacts = $accessor->findAll();
If your data will be serialized in an uncontrolled manner, the approach you suggest is the best. Just make sure to separate your models (e.g. Address book, Contact) from the method of retrieval (eg. get_address_book_xml, get_address_book_sql, etc.)
Of course there are many ways of separating your models from your data-mapping driver. The importance is you find the solution that works best for you given that you're using such different formats.
I'm working on creating a domain layer in Zend Framework that is separate from the data access layer. The Data Access Layer is composed to two main objects, a Table Data Gateway and a Row Data Gateway. As per Bill Karwin's reply to this earlier question I now have the following code for my domain Person object:
class Model_Row_Person
{
protected $_gateway;
public function __construct(Zend_Db_Table_Row $gateway)
{
$this->_gateway = $gateway;
}
public function login($userName, $password)
{
}
public function setPassword($password)
{
}
}
However, this only works with an individual row. I also need to create a domain object that can represent the entire table and (presumably) can be used to iterate through all of the Person's in the table and return the appropriate type of person (admin, buyer, etc) object for use. Basically, I envision something like the following:
class Model_Table_Person implements SeekableIterator, Countable, ArrayAccess
{
protected $_gateway;
public function __construct(Model_DbTable_Person $gateway)
{
$this->_gateway = $gateway;
}
public function current()
{
$current = $this->_gateway->fetchRow($this->_pointer);
return $this->_getUser($current);
}
private function _getUser(Zend_Db_Table_Row $current)
{
switch($current->userType)
{
case 'admin':
return new Model_Row_Administrator($current);
break;
case 'associate':
return new Model_Row_Associate($current);
break;
}
}
}
Is this is good/bad way to handle this particular problem? What improvements or adjustments should I make to the overall design?
Thanks in advance for your comments and criticisms.
I had in mind that you would use the Domain Model class to completely hide the fact that you're using a database table for persistence. So passing a Table object or a Row object should be completely under the covers:
<?php
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();
$db = Zend_Db::factory('mysqli', array('dbname'=>'test',
'username'=>'root', 'password'=>'xxxx'));
Zend_Db_Table_Abstract::setDefaultAdapter($db);
class Table_Person extends Zend_Db_Table_Abstract
{
protected $_name = 'person';
}
class Model_Person
{
/** #var Zend_Db_Table */
protected static $table = null;
/** #var Zend_Db_Table_Row */
protected $person;
public static function init() {
if (self::$table == null) {
self::$table = new Table_Person();
}
}
protected static function factory(Zend_Db_Table_Row $personRow) {
$personClass = 'Model_Person_' . ucfirst($personRow->person_type);
return new $personClass($personRow);
}
public static function get($id) {
self::init();
$personRow = self::$table->find($id)->current();
return self::factory($personRow);
}
public static function getCollection() {
self::init();
$personRowset = self::$table->fetchAll();
$personArray = array();
foreach ($personRowset as $person) {
$personArray[] = self::factory($person);
}
return $personArray;
}
// protected constructor can only be called from this class, e.g. factory()
protected function __construct(Zend_Db_Table_Row $personRow) {
$this->person = $personRow;
}
public function login($password) {
if ($this->person->password_hash ==
hash('sha256', $this->person->password_salt . $password)) {
return true;
} else {
return false;
}
}
public function setPassword($newPassword) {
$this->person->password_hash = hash('sha256',
$this->person->password_salt . $newPassword);
$this->person->save();
}
}
class Model_Person_Admin extends Model_Person { }
class Model_Person_Associate extends Model_Person { }
$person = Model_Person::get(1);
print "Got object of type ".get_class($person)."\n";
$person->setPassword('potrzebie');
$people = Model_Person::getCollection();
print "Got ".count($people)." people objects:\n";
foreach ($people as $i => $person) {
print "\t$i: ".get_class($person)."\n";
}
"I thought static methods were bad
which is why I was trying to create
the table level methods as instance
methods."
I don't buy into any blanket statement that static is always bad, or singletons are always bad, or goto is always bad, or what have you. People who make such unequivocal statements are looking to oversimplify the issues. Use the language tools appropriately and they'll be good to you.
That said, there's often a tradeoff when you choose one language construct, it makes it easier to do some things while it's harder to do other things. People often point to static making it difficult to write unit test code, and also PHP has some annoying deficiencies related to static and subclassing. But there are also advantages, as we see in this code. You have to judge for yourself whether the advantages outweigh the disadvantages, on a case by case basis.
"Would Zend Framework support a Finder
class?"
I don't think that's necessary.
"Is there a particular reason that you
renamed the find method to be get in
the model class?"
I named the method get() just to be distinct from find(). The "getter" paradigm is associated with OO interfaces, while "finders" are traditionally associated with database stuff. We're trying to design the Domain Model to pretend there's no database involved.
"And would you use continue to use the
same logic to implement specific getBy
and getCollectionBy methods?"
I'd resist creating a generic getBy() method, because it's tempting to make it accept a generic SQL expression, and then pass it on to the data access objects verbatim. This couples the usage of our Domain Model to the underlying database representation.