Magento系统中的12种代码设计模式 给出一个需求,解决的方案有很多,设计模式便是其中的最佳方法,可以解决特定环境下的同类问题。设计模式的代码是可重复利用的,对于提高工作效率大有裨益,那从长远角度考虑,是不是应当在代码中尽可能多的使用设计模式呢?明显不是,一名优秀的软件开发者知道何时使用设计模式,并不会无的放矢。早期Magento框架中的比较出色的一点是,其中的绝大部分(甚至所有)使用的设计模式的方式都有其用意所在。 模式1:MVC Model-View-Controller,即模型-视图-控制器,简称MVC,应该是最广为人知的一种设计模式(大多数使用者甚至都不会将它视为设计模式)。这是一种将业务逻辑、页面展示、逻辑分离开来的设计模式。Mageno中使用了大量的xml文件作为逻辑模板,使用pthml(混合了HTML和PHP)文件作为它的视图,剩下的模型依赖Varien的ORM。大多数的业务逻辑发生在模型中,而控制器将模型数据映射到视图,Magento的视图包含了太多的逻辑而显示很笨重,不得不通过一个专门的php类(Block类)进行渲染。 模式2: 前端控制器模式 前端控制器模式确保有且只有一个入口。所有的请求都会先从前端控制器那里走一遭,被识别后路由分发到指定的controller,进行特定的处理。在Magento唯一一个入口文件index.php就起到了前端控制器的作用,它通过Mage::app()方法实现应用环境的初始化并将请求路由到正确的controller中。 模式3:工厂模式 工厂模式的“工厂”二字已经充分表露了它的功能————如工厂的流水线一般统一进行类的实例化。它被广泛应用在Magento的代码库中,负责自动加载系统。在config.xml文件中定义一个module的别名后,工厂就悄咪咪的记录了别名对应的类及类所在的位置。 Mage核心类中有很多辅助实现工厂的方法,其中的Mage::getModel()方法可以接收一个类的别名返回类的实例,如Mage::getModel('catalog/product')返回产品类Mage_Catalog_Model_Product的实例。区别于传统的在代码中直接引入类所在文件并调用类,工厂模式以统一的方式对类进行初始化。 模式4:单例模式 另一种获取类的实例的方法是Mage::getSingleton(),它跟Mage::getModel()方法一样接收一个类的别名,不同之处在于getSingleton在返回实例之前,会先去注册表里瞄一眼,看看这个类是否已经实例化过了,如果实例化过了,那这个实例就可以被共享了。 例如,Magento中的session对象,(如customer session或checkout session),被储存在注册表中,可以在代码不同地方重复使用,而不要每次都重新创建. 模式5:注册模式 所有的单例都存储在内部注册表中,这是全局的存储数据的地方,而且不仅限于内部使用。下面列举的注册相关的方法可以分别实现从注册表中存储,查询,删除数据。 这种注册表的方法通常应用于数据不能传递时的场景下,进行数据的传输。并且数据格式是key-value的格式比如订单生成的时候register一个key,然后在sales_order_save_after事件的observer方法中通过registry读取之前register的key. 模式6:原型模式 原型模式是对工厂模式功能的补充,它定义类的实例可以根据其父类(原型)检索其它类的实例。举个栗子,Mage_Catalog_Model_Product类有一个getTypeInstance方法来获取特定的类Mage_Catalog_Model_Product_Type的对象,后者包含了不适用于其它产品的一系列的方法和属性。 而Mage_Downloadable_Model_Product_Type这个Downloadable产品的类又最终继承了Mage_Catalog_Model_Product_Type类。如果您正在下单并想要调用Downloadable类型产品的特定方法,则需要首先使用原始的产品类的getTypeInstance方法对其进行实例化。 模式7:对象池模式 对象池模式只是一个包含对象的集合,防止它们一次又一次被分配和销毁。在Magento中,对象池模式并不常见,只会在处理严重影响服务器性能的重任务时被使用,例如批量导入产品的时候。可以使用Mage::objects()方法访问对象池(由Varien_Object_Cache类管理) 模式8 迭代器模式 迭代器模式定义了一个公共方法来遍历具有对象的结合。在Magento中,这是由Varien_Data_Collection类实现的,它依次使用各种baked-in的PHP类(如ArrayIterator)来为数组提供更多的OO接口。这样可以确保模型集合始终具有一个通用的API来遍历,而不依赖于实际的模型。 模式9:延迟加载模式 延迟加载确保加载数据被延迟到实际需要的时间点,这导致更少的资源利用。 Magento的延迟加载行为之一就是collection集合。如果使用Mage::getModel('catalog/product')->getCollection()获取产品collection时,并没有操作数据库。只有当load之后,遍历collection中的product对象或者查询collection的数量时,才会对数据库进行读写操作。 模式10:服务定位器模式 服务定位器模式抽取某个服务的检索。它遵守其抽象基础,可以在不破坏任何东西的情况下改变服务,而且可以看到适合其目的的服务。例如,Ryan的数据库连接。另一个例子是Magento的缓存机制,通过Mage::getCache()存储缓存,Mage::getCache()是由Zend或其他供应商提供的缓存存储的代理服务定位器。 模式11:模块模式 任何熟悉Magento开发的人都会很自然的接触模块模式。它基本上定义了不同的功能被分组成独立的模块,它们彼此独立,并且可以根据需要插入到Magento主系统中。在理想情况下,模块模式的实现将确保每个元素都可以被删除或交换。 PHP中模块模式的主角之一是Composer软件包管理器。 虽然Magento严重依赖于模块化架构,但它并不是模块化的。某些功能与核心密切相关,不能轻易改变。还大量使用超全局的Mage核心类,引入了各种不受监管的系统级依赖关系。 模式12:观察者模式 Magento的事件驱动架构是实现观察者模式的结果。通过定义观察者(或监听者),可以挂接额外的代码,随着观察到的事件触发,这些代码将被调用。Magento使用config.xml存储并定义观察者。使用Mage::dispatchEvent($eventName,$data)触发事件,eventName是事件名,data是参数。事件触发后会将查询数据存储,并触发相应的$event观察者。除了使用模块之外,还可以使用事件来定制现有的逻辑,而不用接触现有的代码。 本文来源:https://www.wddqw.com/doc/c84e83854a35eefdc8d376eeaeaad1f34793116e.html