复合模式简介

复合模式将两个或多个模式组合成解决常见或普遍性问题的解决方案,复合模式不是同时使用的一组模式,而是一个问题的通用解决方案。

模型-视图-控制器模式

MVC模式将应用程序分为3个基本部分:模式、视图和控制器。这3个部分是相互关联的,并且有助于将信息的处理与信息的呈现分离开。

MVC模式的工作机制为:模型提供数据和业务逻辑(如果存储和查询信息),视图负责数据的展示(如何呈现),控制器是两者之间的粘合剂,根据用户要求的呈现方式来协调模型和视图。

对于浏览网站:

  • 你是用户,与视图交互。视图就是供给你的网页。
  • 控制器从属兔获取输入并将其发送到模型,然后模型会根据用户执行的操作来完成相应的动作
  • 控制器还可以根据其从用户接受到的操作,要求视图进行相应的改变。
  • 模型将状态变化通知视图。
  • 视图随后展示从模型获得的状态

在这里插入图片描述

  • 模型:声明一个存储和操作数据的类
  • 视图:声明一个类来构建用户界面和显示数据
  • 控制器:声明一个连接模型和视图的类
  • 客户端:声明一个类,根据某些操作来获取某些结果

使用的情况:

  • 当需要改变展示方式而不是改变业务逻辑时
  • 多个控制器可用于使用多个视图来更改用户界面上的展示
  • 再次重申,当模型改变时,视图无序改动,他们是相互独立的。

模型

模型是应用程序的基石,因为它独立与视图和控制器,但是视图和控制器则依赖于模型。

模型还提供了客户端请求的数据。模型还会提供以及改变状态的方法。

模型必须在多个操作中保持一致,否则,客户端可能会损坏或展示过时的数据。

视图-外观

视图用来将数据展示在接口上,共给客户查看。视图可以独立的开发,单不应包含任何复杂的逻辑。

控制器-胶水

控制器作为模型和视图之间的胶水,并且尽量可能的薄

假设我们想要开发一个应用程序,告诉用户云公司提供的营销服务,包括电子邮件,短信和语言设施。

首先开发一个model类,定义产品提供的服务,即电子邮件、短信和语音。

然后,我们来定义view类,提供了将信息反馈给客户端的方法。

class Model(object):
    services = {
        'email':{
            'number':1000,
            'price':2,
        },
        'sms':{
            'number':1000,
            'price':10,
        },
        'voice':{
            'number':1000,
            'price':15
        }
    }
class View(object):
    def list_services(self, services):
        for svc in services:
            print(svc,' ')
    def list_pricing(self, services):
        for svc in services:
            print("For", Model.services[svc]['number'],svc,"message you pay $", Model.services[svc]['price'])

class Controller(object):
    def __init__(self):
        self.model = Model()
        self.view = View()
    def get_services(self):
        services = self.model.services.keys()
        return (self.view.list_services(services))
    def get_pricing(self):
        services = self.model.services.keys()
        return (self.view.list_pricing(services))
class Client(object):
    controller = Controller()
    print("Services Provided:")
    controller.get_services()
    print("Pricing for Services:") 
    controller.get_pricing()
Services Provided:
email
sms
voice
Pricing for Services:
For 1000 email message you pay $ 2
For 1000 sms message you pay $ 10
For 1000 voice message you pay $ 15

MVC设计模式的UML类图

在这里插入图片描述

  • Model类:定义与客户端的某些任务有关的业务逻辑或操作
  • View类:定义客户端查看的视图或展示,模式根据业务逻辑向视图呈现数据
  • Controller类:视图与模型之间的接口
class Model(object):
    def logic(self):
        data = 'Got it!'
        print("Mode1: Crunching data as per business logic")
        return data
class View(object):
    def update(self, data):
        print("View: Updating the view with results: ",data)
    
class Controller(object):
    def __init__(self):
        self.model = Model()
        self.view = View()

    def interface(self):
        print("Controller: Relayed the Client asks")
        data = self.model.logic()
        self.view.update(data)
class Client(object):
    print("Client: asks for certain information")
    controller = Controller()
    controller.interface()
Client: asks for certain information
Controller: Relayed the Client asks
Mode1: Crunching data as per business logic
View: Updating the view with results:  Got it!

MVC模式应用

假设用Tornado Web应用程序框架来开发一个单页应用程序。这个应用程序用于管理用户的各种任务,同时用户还具有添加任务,更新任务和删除任务的权限。

导入模块

import tornado
import tornado.web
import tornado.ioloop
import tornado.httpserver
import sqlite3

在MVC中的模型,在Tornado中,数据库操作是在不同的处理程序下执行的。处理程序根据用户在Web应用程序中请求的路由对数据库执行操作。

  • IndexHandler:返回存储数据库中所有任务,返回一个与关键任务有关的字典。
  • NewHandler:添加新任务
  • UpdateHandler:将任务标记为完成或重新代开给定任务时非常有用。
  • DeleteHandler:删除指定的任务。

还开发了一个_execute()方法,以SQLite查询作为输入并执行所需的数据库操作。_execute()方法对SQLiteDB执行下列的操作

  • 创建SQLiteDB连接
  • 获取游标对象
  • 使用游标对象执行事务
  • 提交查询
  • 关闭连接
class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        query = "select * from task"
        todos = _execute(query)
        self.render('index.html',todos = todos)

class NewHandler(tornado.web.RequestHandler):
    def post(self):
        name = self.get_argument('name',None)
        query = "create table if not exists ask (id INTEGER PRIMARY KEY, name TEXT, status NUMERIC)"
        _execute(query)
        query = "insert into task (name status) values ('%s', '%d')" %(name,  1)
        _execute(query)
        self.redirect('/')
    def get(self):
        self.render("new.html")
class UpdateHandler(tornado.web.RequestHandler):
    def get(self, id,, status):
        query = "update task set status=%d where id=%s"%(int(status), id)
        _execute(query)
        self.render('/')
        

视图:

  • index.html 用于列出所有任务的模板
  • new.html 用于创建新任务的视图
  • base.html 继承其他模板的基本模板

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    {% block header%}
    {% end %}
</head>
<body>
    {%block body%}
    {% end %}
</body>
</html>

index.html

{% extends 'base.html'%}
<title>ToDo</title>
{%block body%}
<h3>Your Tasks</h3>
<table border="1">
    <td>Id</td>
    <td>Name</td>
    <td>Status</td>
    <td>Update</td>
    <td>Delete</td>
    <tr>
        {% for todo in todos %}
            <td>{{todo[0]}}</td>
            <td>{{todo[1]}}</td>
            {% if todo[2] %}
                <td>Open</td>
            {% else %}
                <td>Closed</td>
            {% end %}
            {% if todo[2] %}
                <td><a href="/todo/update/{{todo[0]}}/0">Close Tas</a></td>
            {% else %}
                <td><a href="/todo/update/{{todo[0]}}/1">Open Task</a></td>
            {% end %}
            <td><a href="/todo/delete/{{todo[0]}}">X</a></td>
        {% end %}
    </tr>
</table>
<div>
    <h3><a href="/todo/new">Add Task</a></h3>
</div>
{%end%}

new.html

{% extends 'base.html'%}
<title>ToDo</title>
{% block body%}
    <div>
        <h3>Add Task to your List</h3>
        <form action="/todo/new" method="post" id="new">
            <p>
                <input type="text" name="name" placeholder="Enter task"/>
                <input type="submit" class="submit" value="add"/>
            </p>
        </form>
    </div>
{% end %}

应用程序的路由相当于MVC中的控制器

  • /:列出所有任务的路由
  • /todo/new:创建新任务的路由
  • /todo/update:将任务状态更新为打开或关闭路由
  • /todo/delete:删除已完成任务的路由
class RunApp(tornado.web.Application):
    def __init__(self):
        Handlers = [
            (r'/',IndexHandler),
            (r'/todo/new',NewHandler),
            (r'/todo/update/(\d+)/status/(\d+)',UpdateHandler),
            (r'/todo/delete/(\d+)',DeleteHandler)
        ]
        settings = dict(
            debug = True,
            template_path='templates',
            static_path = "static"
        )
        tornado.web.Application.__init__(self, Handlers,**settings)

if __name__ == '__main__':
    http_server = tornado.httpserver.HTTPServer(RunApp())
    http_server.listen(5000)
    tornado.ioloop.IOLoop.instance().start()

优点

  • 有助于提高可维护性、强制松耦合、并降低复杂性

  • 开发工作可以独立运行

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐