Web编程技术交流网

博客文章

欢迎访问本站博客,本站免费提供大量网站编程的技术资料和娱乐信息,欢迎编程交流1群讨论!

设计模式在Magento中的应用–工厂

设计模式在Magento中的应用–工厂

工厂模式是一个在软件设计中使用得很频繁的一设计模式,他归属创建模式。所谓工厂就是生产东西的地方,比如玩具厂生产玩具,农场生成水果/蔬菜等等。下面我们先学习或者复习一下工厂这种设计模式,我们以农场中的农民生产水果和蔬菜为例进行分析.
我们先定义一个产品抽像类,是所有产品的基类,我特地在这里加了__get/__set两个魔术方法,因为他在Magento中的Varien_Object也定义了这两个方法,这两个方法在一些框架经常使用到,如yii.这两个方法很好用,不像java了,要定义很多set/get方法,呵呵。
代码块1:

abstract class Product {
private $_data = array();
public function __set($var, $value)
$this->_data[$var] = $value;
}
public function __get($var)
{
if (isset($this->_data[$var])) {
return $this->_data[$var];
}
return false;
}
}

代码块2:水果的定义

class Fruit extends Product{
//方法或者变量定义
}

代码块3:蔬菜的定义

class Vegetables extends Product{
//方法或者变量定义
}

假设我们农场为了节约成本只有一个农民,而且刚开张只生产苹果和萝卜,那他又生产菜果,又生产萝卜.
菜果类:代码块2.1

class Apple extends Fruit {
//方法或者变量定义
}

萝卜类:代码块3.1

class Radish extends Vegetables {
//方法或者变量定义
}

代码块4:农场的定义,他的方法farmerAll相当一个农民

class Farm {
public static function farmerAll($productType) {
if (‘fruit’ == $productType) {
$fruit = new Apple ();
return $fruit;
}
else if (‘vegetables’ == $productType) {
$vegetables = new Radish();
return $vegetables;
}
else {
echo ‘暂不生产’;
return false
}
}
}

现在来了一个客户买,他必须经过农场的农民来买,不然是就算偷菜了,呵呵。
代码如下:代码块5

$fruit = Farm::farmerAll(‘fruit’);
$vegetables = Farm::farmerAll(‘vegetables’);

农场发展了,决定专业化生产,一个农民生产一种产品,那么农场的定义发生变化:
代码块6:

class Farm {
public static function farmerFruit() {
$fruit = new Apple();
return $fruit;
}
public static function farmerVegetables() {
$vegetables = new Radish();
return $vegetables;
}
}

现在来了一个客户买,他找到相应的农民进行。
代码块7:

$fruit = Farm::farmerFruit();
$vegetables = Farm::farmerVegetables();

因为农场只生产菜果和萝卜,所以客户买的时候不要指明是那种水果和蔬菜,现在农场 发展了,准备再生产香蕉和白菜,类如下
香蕉类:代码块2.2

class Banana extends Fruit {
//方法或者变量定义
}

白菜类:代码块3.2

class Cabbage extends Vegetables{
//方法或者变量定义
}

但是为了成本考察不再追加农民.那么水果农民将生产两种水果,蔬菜农民生产两种蔬菜,此时,外界客户来买必须指定要那一种,不然农民会搞不清给那种给客户(只有一种时只能给那一种,呵呵)。此时的农场类变成了:
代码块8:

class Farm {
public static function farmerFruit($fruitType) {
if (‘apple ‘ == $fruitType) {
$apple = new Apple();
return $apple;
}else if (‘banana’ == $fruitType) {
$banana = new Banana();
return $banana;
}else {
echo ‘暂不生产’;
return false;
}
}
public static function farmerVegetables($vegetablesType) {
if (‘radish ‘ == $vegetablesType) {
$radish = new Radish();
return $radish;
}else if (‘cabbage’ == $vegetablesType) {
$cabbage = new Cabbage();
return $cabbage;
}else {
echo ‘暂不生产’;
return false;
}
}
}

我们已一个农场的发展,分析了工厂模式。在这个工厂模式中他有两类产品,由两个工厂方法来生产这两类产品。

XML与工厂模式

现在公司再次发展,需要再增加一个水果和蔬菜,那么我们再增加两个产品类,同时我们要修改农场中的两个工厂方法(农民),这与开闭原则是不相符的。
所以在这里我们引与xml文件,来处理这个问题。
代码块9:





test/apple.php


test/banana.php



test/radish.php


test/cabbage.php


上面xml表示有两类产品下都有两个产品,其file节点表示产品类存在那个地方。如果此节点为空,则不引入。apple/banana这类节点表示类名,要把第一个字母输入为大写就可以了。现在我们来修改一下农场类.
代码块10:

class Farm {
public static function getClassName($type) {
//通过file_get_contents得到xml文件内容
//通过simplexml_load_string解析xml文件
//根据$type 找到file文件并include.
//return 类名
}
public static function farmerFruit($fruitType) {
$className = self::getClassName(‘fruit/’ . $fruitType);
return new $className();
}
public static function farmerVegetables($vegetablesType) {
$className = self::getClassName(‘vegetables/’ . $vegetablesType);
return new $className();
}
}

在这里我并没有写全getClassName,读者可以自行完成,当作一个练习。
这样当要再增加两个产品类时,我们不要修改农场类,只要在xml中加入节点就,农民就知道要生产他了。这样在没有修改源程序的情况下(当然修改了配置文件)实现了系统的扩展。同时由于类名是从getClassName统一生成的,所以以后要增强功能,也可以只修改这个方法就可以了。

在很多框架的工厂模式的应用都使用xml文件,如spring等。下面我们进入我们的Magento中是怎样应用Mageto的。

Magento工厂的应用
1、找出Magento中的产品分类。有如下几类:
Helper/model/resourceModel/block
2、Magento谁充当农场类? 由Mage.php中的Mage类充当。
3、谁充当农民?
helper的农民:由helper方法充当
model的农民:由getModel/getSingleton(单例)充当
resourceModel的农民:由getResourceModel/getResourceSingleton(单例)充当
block的农民:由getBlockSingleton(单例)充当,这个农民把生产的任务分给了Mage_Core_Model_Layout的getBlockSingleton农民.
Block还有一个农场类叫:Mage_Core_Model_Layout,里面的农民是:createBlock/getBlockSingleton.
4、xml的应用:
helper 的xml:
代码块11:



Youthor_Homepage_Helper

取得一个helper产品对象$helper = Mage::helper(‘homepage/data’); 相当于找helper节点下的homepage节点,只不过返回的类名是class值加上data,如:Youthor_Homepage_Helper_Data(记得把data第一个字母大写),这与我们分析中的那个xml文件有一点不一样,但原理是一样的,不过这里的文件是根据类名自动引入的。如果是这样$helper = Mage::helper(‘homepage/homepage_test’),那么类名是Youthor_Homepage_Helper_Homepage_Test.由于Magento是基于Zend Frame的,所以它的类名同时表示了他的类文件所在的文件夹和类文件名,Youthor/Homepage/Helper/Homepage/Test.php有了这个规则,Magento才知道自动引入那个文件,以上的分析对model/resourceModel/block同样实用。

block的的xml:



Youthor_Homepage_Blcok

取得一个block产品对象$block = Mage::getBlockSingleton(‘homepage/test’);

model/resourceModel的的xml:



Youthor_Homepage_Model
homepage_mysql4


Youthor_Homepage_Model_Mysql4

取得一个model产品对象$model = Mage::getModel(‘homepage/test’); 取得单例model对象:$model = Mage::getSingleton(‘homepage/test’);

取得资源model,$resourceModel = Mage::getResourceModel(‘homepage/test’); 取得单例资源model对象:$resourceModel= Mage::getResourceSingleton(‘homepage/test’); 资源model的类名为Youthor_Homepage_Model_Mysql4_Test,它是从homepage找到homepage节点从而找到resourceModel节点的值homepage_mysql4,再由homepage_mysql4找到homepage_mysql4节点下的class节点的值Youthor_Homepage_Model_Mysql4再加上test(记得第一个字母大写)。

在工厂方法的第一个参数的/前的那个值 相应产品类型下的一个节点,(如homepage),在magento中一般认为是模块名,其实这不是必须的,他只是一个标示工厂方法怎样来找这个节点的名称而已,只要与你的工厂方法的第一个参数的/前的那个值相同就可以了,只不过在Magento中最好与模块名一致.



顶一下
(0)
100%

订阅分享回复

踩一下
(0)
100%

如果您觉得此内容对您有价值,可以点击上面的按钮支持作者,谢谢^_^
12,291 次

发表于分类: magento

发表一下您的观点: (0) →

发表评论

+=

无觅相关文章插件,快速提升流量