Magento中的设计模式详解
1. Model View Controller(MVC)模式
MVC是一种设计模式,用于将业务逻辑、表示和耦合逻辑分离。Magento在很大程度上使用XML作为模板逻辑以及HTML混合PHP文件用于视图展示。模型由Varien ORM支持。大部分业务逻辑发生在模型中,而控制器则将模型数据映射到视图上。
因为Magento的视图很“臃肿”,通常包含很多逻辑,所以视图经常具有一个额外的PHP类(块系统),用于帮助渲染。
2. 前置控制器模式
前置控制器模式确保只有一个入口点。所有请求都会被检查并路由到指定的控制器,然后根据规范进行处理。前置控制器负责初始化环境并将请求路由到指定的控制器。
Magento只有一个入口点(index.php),它将初始化应用程序环境(Mage::app()),然后将请求路由到正确的控制器。
3. 工厂模式
工厂模式负责实例化类。它在Magento的代码库中被广泛使用,并利用Magento的自动加载系统。通过在模块的config.xml中定义别名,可以让工厂知道在哪里可以找到类。
Mage核心类中有各种工厂辅助方法之一是getModel()。它接受一个类别名,然后返回该类的实例。工厂模式将通过统一的方式实例化类,而不是在代码库中散布包含调用。
4. 单例模式
获取类的实例的另一种方法是调用Mage::getSingleton()。它接受一个类别名,并在返回实例之前,检查内部注册表是否已经实例化了这个类 - 这会导致共享实例。必须使用这种方法的一个示例是会话存储,应在整个代码库中共享,而不是每次创建新实例。
5. 注册表模式
所有单例都存储在内部注册表中:全局作用域的容器用于存储数据。它不仅供内部使用。Mage::register($key, $value),::registry($key)和::unregister($key)方法可以分别用于存储、检索和删除注册表中的数据。当无法传递数据时,注册表通常用于在范围之间传输数据。
6. 原型模式
工厂模式(列表中的#3)停止的地方就是原型模式继续的地方。它定义了类的实例可以根据其父类(原型)检索特定的其他类实例。值得注意的一个示例是Mage_Catalog_Model_Product类,它具有getTypeInstance方法,用于检索具有特定子集的特定Mage_Catalog_Model_Product_Type方法和属性,而这些方法和属性并不适用于所有产品。例如,Mage_Downloadable_Model_Product_Type最终扩展了Mage_Catalog_Model_Product_Type。如果您正在遍历订单并想调用可下载产品的特定方法,则需要首先使用原始产品的getTypeInstance方法进行因式分解。
7.对象池模式
对象池模式只是一个盒子,其中包含对象,因此它们不必一遍又一遍地分配和销毁。它在Magento中很少使用,仅用于资源很快会受到限制的繁重任务,例如导入产品。对象池(由Varien_Object_Cache管理)可以通过Mage::objects()访问。
8.迭代器模式
迭代器模式定义了一种共享方式来迭代具有对象的容器。在Magento中,这由Varien_Data_Collection处理,其又使用各种内置PHP类(如ArrayIterator)以获得更多针对数组的面向对象接口。这确保了模型集合将始终具有常见的API可供迭代,而不依赖于实际模型。
9.延迟加载模式
延迟加载确保加载数据被延迟直到实际需要它的时候。这导致使用的资源更少。Magento的延迟加载行为之一是集合的行为。如果您要检索产品集合Mage::getModel('catalog/product')->getCollection(),则仅当您实际访问集合时(例如,通过迭代它或检索找到的模型的计数)才会触及数据库。
10.服务定位器模式
服务定位器模式抽象了某个服务的检索。这允许更改服务而不会破坏任何东西(因为它遵循其抽象基础),但也可以根据其目的自由地获取服务。
Ryan用数据库连接举例。另一个例子是Magento的缓存机制,其中Mage::getCache()是Zend或其他供应商提供的缓存存储的服务定位器。
11.模块模式
熟悉Magento开发的人都会遇到模块模式。它基本上定义了将不同的域分组到单独的模块中,这些模块独立于彼此并可以根据需要插入到主系统中。在理想情况下,模块模式的实现将确保可以删除或交换每个元素。模块模式在PHP中的代表之一是Composer包管理器。
尽管Magento严重依赖于模块化架构,但它并非完全模块化。某些功能与核心密切相关,不易更改。还有超全局Mage核心类的大量使用,引入各种系统范围的依赖关系,不易监控。
12.观察者模式
Magento的事件驱动架构是实现观察者模式的结果。通过定义观察者(或监听器),可以挂接额外的代码,当观察到事件发生时,这些代码将被调用。Magento使用XML数据存储来定义观察者。如果使用Mage :: dispatchEvent($ eventName,$ data)触发事件,则会查询数据存储,并触发适用于$ event的相应观察者。