注意: 此问题已更新,以提供比以前更多的细节和洞察力。使用MVC,OO和设计模式的软件设计入门
更新: 我只想对所有回复的人表示感谢。对于Widget,哪种设计模式最适合,我仍然处于黑暗中。也许工厂或生成器模式之一?
我刚刚开始了一个新项目,需要使用MVC,OO和设计模式。
这里有个想法:设想一个显示一组小部件的页面。这些小部件(通常)是基于数据库中几个独立表中包含的数据的图表。我使用一个运行的页面示例来报告学生的表现。
高层次的需求
- 显示一组(HTML仅)小部件的页面。
- 小部件的数据将基于数据库查询。
- 该页面可用于查看包含类似布局数据的单独数据集。例如,单个页面将显示报告单个学生表现的各个方面的小部件。
- 想看另一个学生的表现,拉另外一页。不需要为不同的学生显示不同的小部件(尽管稍后可能会很好)。
- 可能有很多学生,但数据库中包含的数据同样是为所有学生制定的。
- 小部件显示的方式可以很容易地进行更改(比如将小部件从饼图显示为条形图显示)。
- 小工具应该能够快速创建。
低级别要求
- 目前的数据并没有改变,因此部件不会需要自动更新自己。
- 小工具可能表示两件事的比例(例如,失败测试与成功测试的比例为饼图),一系列点或有时单个数值。
- 新窗口小部件的开发应该轻而易举,现有的代码不需要修改。
- 要使用的框架:基于MVC的Zend Framework。
定义窗口小部件有三件事情:要报告的数据集(在上面的示例中,学生ID),描述所报告的度量的查询以及渲染模式(条形图,时间序列等)。
这里是一个打破的责任MVC的每一层的一通:
查看: Zend的看法与PHP的HTML模板注入。它们将包含几种类型的小部件中的一种。小部件的各种形式,包括:静态JPEG图像(从远程站点即加载:<img src="http://widgetssite.com?x=2&y=3"/>
,基于JSON JavaScript的窗口小部件,或各种(饼图,柱状图等)的图表
控制器:创建窗口小部件,将它们分配给视图之后,要在页面上显示的一组小部件需要保存在某处,因为我不能想到在视图中这样做的好方法,我将它添加到控制器中如果有更好的地方请留言,控制器还必须处理其他输入参数并将它们传递给小部件,例如,可以在url行传递的data_set id为http:/.../report/?student_id=42
模型:Zend Framework中的模型负责提取数据,因此很可能包含每个用于访问数据库的窗口小部件的类。
几点:
这里的模型,代表了一个特定插件的数据。因此,必须知道查询将会是什么,以便将获取数据所需的表拉到一起。
还有一个额外的处理步骤,在小部件可以呈现数据之前很有可能是必要的。这取决于将使用哪个渲染器。有时它可能需要从返回的数据中形成一个url。其他时候,一个JSON数组。其他时候可能会创建一些标记。这可以在模型或控制器或视图中进行。除非任何人可以想到将其移动到控制器或视图的充分理由,否则最好让它生活在模型中,并保持视图和控制器精简。
同样,一个小部件将由3件东西,它的参数,它的数据和它的渲染器组成。
问题的一大部分是:在面向对象设计中表示小部件的好方法是什么?我已经问过这一次,无法得到答案。 是否有可应用于Widgets的设计模式,对于此项目最有意义?
这里是在widget的相当简单的类第一遍:
class Widget{ //method called by the view render() {//output the markup based on the widget Type and interleaved the processed data} //methods called by the controller: public function __construct() {//recieve arguments for widget type (query and renderer), call create()} public function create() {//tell the widget to build the query, execute it, and filter the data} public function process_data() {//transform into JSON, an html entity etc} //methods called by the model: public function build_query() {...}; public function execute_query() {...}; public function filter_data() {...}; }
看着它,我已经可以看到一些问题。
例如,将在控制器中创建的窗口小部件传递给视图以进行渲染很简单。
但是,当涉及到实施模型,它似乎不是那么直截了当。表格网关模式比ORM更容易实现。但是,由于表格网关模式对于每个模型/表格都有一个类别,因此它似乎不适合该账单。我可以为特定的表创建模型,然后在其中实例化任何其他需要的模型。但这似乎不适合表格网关模式,而是适合ORM模式。 可以使用多个表来实现表格网关模式吗?还有什么替代方法?控制器创建窗口小部件并且窗口小部件创建模型是否有意义?
出现的另一个问题是,此设计无法轻松创建窗口小部件。即。假设我想创建一个PiechartWidget,可以重复使用多少代码?使用一些面向对象的概念,比如接口或抽象类/方法和继承,会不会更有意义?
假设我抽象了Widget类,所以只有共享方法被具体定义,其余的被声明为抽象方法。修订Widget类,使之抽象(第二次):
abstract class Widget{ private $_type; private $_renderer; //methods called by the controller: //receive arguments for widget type (query and renderer), protected function __construct($type, $renderer) { $this->_type = $type; $this->_render = $renderer; $this->create(); } //tell the widget to build the query, execute it, and filter the data private function create() { $this->build_query(); $this->execute_query(); $this->filter_data(); } //methods called by the model: abstract protected function build_query(); protected function execute_query() { //common method } abstract protected function filter_data(); //method called by controller to tranform data for view //transform into JSON, an html entity etc abstract protected function process_data(); //method called by the view //output the markup based on the widget Type and interleave the processed data abstract protected function render(); }
这是一个好的设计?如何改进?
我认为编写一个新的小部件需要至少一些新的代码来构建查询,并可能过滤数据,但它应该能够使用预先存在的代码来处理其余所有功能,包括已经存在的渲染器。
我希望任何人都可以提供此设计的至少一些反馈。验证它? 撕开它。叫我白痴。这也没关系。我可以使用任何向前牵引。
一些具体问题:
Q1。作为Widget类的一部分或作为单独的类来实现渲染器的最佳方式是什么? 1A。如果是单独的,它将如何与widget类进行交互? Q2302。我怎样才能改进这个设计来简化新类型的小部件的创建?
Q3。最后,我觉得在数据封装方面我缺少一些东西。数据封装如何与需求相关并在这种情况下发挥作用?
http://en.wikipedia.org/wiki/Presentation-abstraction-control – alex 2010-01-22 02:18:06
这是使用Zend框架,所以MVC是固有的。 – hinghoo 2010-01-22 02:25:38
所有的数据都会以你给出的例子的比例的形式出现,还是有些小部件会显示一个比例,而其他小部件会显示比如一组点? – mattjames 2010-01-22 02:27:41