Jump to content

Archived

This topic is now archived and is closed to further replies.

mouseywings

When to use the Factory Pattern

Recommended Posts

So I was stumbling around with Repositories and Interfaces and got a decent grasp on it. However, I started running into abstraction and started to implement a little bit of the Factory design.

 

How often is this typically used? It seems like I should be using  Factory with 90% of my Repositories since there are different types of Items, Tutorials, Random Events, etc.

 

Items

- Food

- Weapon

- Toy

 

Tutorials

- Newbie

- Farming

 

Random Events

- Coin Giving

- Item Giving

- Item Draining

 

Things like this... so all of them have similar methods involved. So they each have a base method, for example.. an Item child class would always have the use() method and a factory would determine which kind of object to initiate from your controller just from the item model being passed through. So therefore you can call use() on the repository instance it returns.

Then I was moving onto my tutorials and random events and it just seemed very similar.

 

So in most cases, will factories be a huge plus? Just wanted some general opinions from the PHP developers =)

Thanks!

Share this post


Link to post
Share on other sites

The "similar methods" thing is inheritance and polymorphism at work: code doesn't necessarily need to know the exact type of item, just that it's an item and can be use()d.

 

Factories can be used a lot, even to the point of factories of factories, and for the most part all you're doing is adding a bit of (worthwhile) overhead. If you find yourself needing if or switch blocks to construct the different types of classes, a factory is probably a good idea.

 

- Items probably could use a factory. Somehow you can identify an item, right? Like the string "food" or "weapon" or "toy". Perhaps with some other information useful to the item itself. A factory can be used there: if you can standardize on a constructor, like

public function __construct(array $config) {
then you can use a factory.

public static function factory($item, array $config) {
	// if your item classes are all named uniformly, like "FoodItem", and you have an item identifier "food"
	$class = ucfirst($item) . "Item";
	if (class_exists($class)) {
		return new $class($config);
	} else {
		trigger_error("No such item '{$item}'", E_USER_WARNING);
		return null;
	}
}
- Tutorials don't actually sound like they need a factory. I'd imagine that a tutorial is "started" in very specific places in code, and so adding more tutorials is not just a matter of writing a new class.

 

- Random events probably have a bit of information attached to each, like the weight/probability of the event, but it's quite possible that you can use a factory here like you can for items.

Share this post


Link to post
Share on other sites

The "similar methods" thing is inheritance and polymorphism at work: code doesn't necessarily need to know the exact type of item, just that it's an item and can be use()d.

 

Factories can be used a lot, even to the point of factories of factories, and for the most part all you're doing is adding a bit of (worthwhile) overhead. If you find yourself needing if or switch blocks to construct the different types of classes, a factory is probably a good idea.

 

- Items probably could use a factory. Somehow you can identify an item, right? Like the string "food" or "weapon" or "toy". Perhaps with some other information useful to the item itself. A factory can be used there: if you can standardize on a constructor, like

public function __construct(array $config) {
then you can use a factory.

public static function factory($item, array $config) {
	// if your item classes are all named uniformly, like "FoodItem", and you have an item identifier "food"
	$class = ucfirst($item) . "Item";
	if (class_exists($class)) {
		return new $class($config);
	} else {
		trigger_error("No such item '{$item}'", E_USER_WARNING);
		return null;
	}
}
- Tutorials don't actually sound like they need a factory. I'd imagine that a tutorial is "started" in very specific places in code, and so adding more tutorials is not just a matter of writing a new class.

 

- Random events probably have a bit of information attached to each, like the weight/probability of the event, but it's quite possible that you can use a factory here like you can for items.

 

 

 

Thanks for your reply! Cleared it up a bit for me =)

 

This is what I had so far in my head for the Item Factory:

<?php

interface IItemRepo {

	public function use( $id );

}

class ItemFactory {

	public function make( $id )
	{
		$item = $this->model->getById( $id );

		if($item->type == 1)
		{
			return new FoodItemRepo( $item );
		}
	}

}

abstract class ItemRepo implements IItemRepo {

	protected $type;
	protected $model;

	public function __construct(Item $item)
	{
		$this->model = $item;
	}

	public function setType( IItemRepo $type )
	{
		$this->type = $type;
	}
	
	abstract function use( array $attributes );

	public function remove( $id )
	{
		$this->model->whereId( $id )->delete();
	}

	public function removeAll( $id )
	{
		$this->model->whereItemId( $id )->delete();
	}

}

class FoodItemRepo extends ItemRepo {

	public function __construct(Item $item)
	{
		$this->model = $item;
		$this->setPet( new Pet );
	}

	public function setPet( IPetRepo $pet )
	{
		$this->pet = $pet;
	}

	public function use( array $attributes )
	{
		// Raise health
		$this->pet->raiseHunger( $attributes->pet );

		// Remove item from inventory
		$this->remove( $attributes->item );
	}

}

// www.sitename.com/inventory/item/remove/29
// www.sitename.com/inventory/item/use/29

class Item {

	public function setItem( $item )
	{
		$this->item = ItemFactory::make( $item );
	}

	public function getUse( $id )
	{
		$this->data['item'] = $this->item->get();

		$this->render('content', 'inventory.item.index', $this->data);
	}

	public function postUse( $id )
	{
		$this->item->use( Input::all() );
	}

}

Am I going about the Factory::make() the right way? Passing the Item Model to it so it grabs it's type by there?

Share this post


Link to post
Share on other sites

Yeah, that's fine.

 

Off-topic: don't name that one method "use". You must be using PHP 5.2 because in 5.3+ that's a keyword and you can't use it as a method name. On that note, you should upgrade! PHP is at 5.6 now and there's been a lot of time elapsed, not to mention changes made, since 5.2.

Share this post


Link to post
Share on other sites

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.