Welcome Guest, Not a member yet? Register   Sign In
Implementing a factory pattern in the Model Layer of CI
#1

[eluser]venugopal[/eluser]
Please correct if this approach is wrong or suggest any other approach to achieve this.

We are designing an ECommerce platform using CI. There are multiple shops and the same product can be made available in multiple shops. But the properties of the product differ from shop to shop.

e.g price of the product A in shop 1 is $5 and in shop 2 its $5.2 etc. But the basic properties like name, description etc are same across all shops.

I am trying to design something like this

abstract class product
{
....function setName();
....function getName();
....function setPrice();
....function getPrice();
}
class Shop1Product extends product
{
....function setPrice()
....{
........ load the price from the DB and return
....}
....function getPrice() { // }
}
class Shop2Product extends product
{
....function setPrice()
....{
........ load the price from the DB and return
....}
....function getPrice() { // }
}
class ProductFactory
{
....function getProduct($productId)
....{
.......//load the context of the current shop which is available by some other means
.......accordingly
...........return newShop1Product();
.......or
...........return newShop2Product();
....}
}


I want these classes to stay in MODEL Layer and the CONTROLLER should get either Shop1Product or Shop2Product from the ProductFactory. Which class should extends CI_Model Class and what should be the code in the Contoller.
#2

[eluser]titoneo[/eluser]
Class product as "product.php" in Model folder...

Code:
class Product extends Model
{
....function setName();
....function getName();
....function setPrice();
....function getPrice();

}

Class Shop1Product as "shop1product .php" in Model folder...

Code:
require_once("product.php");

class Shop1Product extends Product{


}

in the controller...

Code:
$this->load->model("shop1product");
#3

[eluser]venugopal[/eluser]
Thanks for the solution. But its not a factory design.

In the controller , I want to load the model like this
$this->load->model("product");

And the model product should get the context object from session and load either shop1product model or shop2product model.

$this->product->getPrice(); // this returns the price of product in shop1 or shop2 depending on the model loaded
$this->product->getName(); // a function which is defined in product model


This way the code in the controller need not know which model it has to load. It will be always the same code irrespective of shop1 or shop2, but we always get the data from the model specific to the shop.
#4

[eluser]titoneo[/eluser]
Oh yes, I forgot the factory design!

Then you need do this in the controller:

Code:
$this->load->model("factoryproduct");
$product = $this->factoryproduct->getProduct();
or maybe... (if is static method)
Code:
$this->load->model("factoryproduct");
$product = factoryproduct::getProduct();

within the method, I would do something like this:

Code:
.......//load the context of the current shop which is available by some other means
.......accordingly
           require_once("shop1product.php")
...........return new Shop1Product();
.......or
          require_once("shop2product.php")
...........return new Shop2Product();

Implementation of the factory should not reside in the product class
#5

[eluser]mddd[/eluser]
Why would you take such a complex approach when a single Product class could do the same thing?
Code:
class Product_model extends Model
{
   var $shop_id;
   var $name;
   var $price;

   function __construct()
   {
      $this->shop_id = $this->session_model->get_shop_id();
   }

   function load_product($product_id)
   {
      $this->name = // load product name here using product_id
      $this->price = // load price here, using shop_id and product_id
   }

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

   function get_price()
   {
      return $this->price;
   }
}

I don't think creating subclasses for each shop is the way to go. It doesn't scale. What if there are 20 shops? You would have 20 classes, all doing exactly the same thing. While in fact you could have all the logic you need (loading some stuff depending on a certain id) in one simple method of a simple product class.

I think subclasses are in order when they have a number of things in common but some things different. In your case, they have everything in common! Only the values are different. But that doesn't make it necessary to have different classes.
For example: if some products have a 'size' property that you can set, and that would reflect in a different price, then it would make sense to have a 'sizeable_product' class. But here, they all have a name, price, etc.
#6

[eluser]titoneo[/eluser]
mddd , because I think the product table is the same for both classes, but the handling is different in each case, isn't it?

If the problem is that were different tables, this would be a solution:


Code:
class Product extends Model{

   var $tablename;

   //constructor
   function Product(){
      parent::Model();
      //decide tablename
      ...........$this->tablename = 'productShop1';
      .......or
      ...........$this->tablename = 'productShop2';

   }

   //when you perform a query...
   function getProducts(){
       $query = $this->db->get($this->tablename);
   }
}
#7

[eluser]venugopal[/eluser]
I just gave an example, but there are some common things across shops and there are many uncommon things also. I want all the common things to be placed in the abstract model and the specific things to be placed in the sub classes.

The above solution is fine if we have the behaviour(method) is same for all shops.
In my case, the behaviour is also different. I cannot write IF-ELSE-IF in models to achieve different behaviours for different shops.

For me it looks like inheritance with factory model is the only way to achieve this. Any other thoughts?

Without Code Igniter, achieving this is very easy Wink, but looking for some thing in CI
#8

[eluser]Brayan[/eluser]
I don't know if I get it right.. but why don't you use the strategy pattern ?

the requests are based on a prompt basis of objects, that can behave as requested by the user, and expected by the hierarchical structure of the application.

sorry if it's not what you're looking for




Theme © iAndrew 2016 - Forum software by © MyBB