第 2 部分 - 体系结构

构建跨平台应用的一个关键原则是创建一个体系结构,使其能够最大限度地实现跨平台代码共享。 遵循以下面向对象的编程原则有助于构建架构良好的应用程序:

  • 封装 - 确保类甚至体系结构层只公开执行所需函数的最小 API,并隐藏实现详细信息。 在类级别,这意味着对象的行为就像“黑盒”,使用代码时不需要知道它们是如何完成任务的。 在体系结构级别,这意味着实现“外观”等模式,它们鼓励使用简化的 API,以便在更抽象的层中代表代码编排更复杂的交互。 这意味着 UI 代码(例如)只应负责显示屏幕和接受用户输入;绝不直接与数据库交互。 同样,数据访问代码应只读取和写入数据库,但绝不直接与按钮或标签交互。
  • 职责分离 - 确保每个组件(在体系结构和类级别)都有清晰明确的目的。 每个组件应仅执行其定义的任务,并通过可供其他需要使用它的类访问的 API 公开该功能。
  • 多形性 - 对支持多个实现的接口(或抽象类)进行编程意味着核心代码可以跨平台编写和共享,同时仍与特定于平台的功能进行交互。

自然结果是一个根据现实世界或具有单独逻辑层的抽象实体建模的应用程序。 将代码分成不同的层使应用程序更易于理解、测试和维护。 建议每个层中的代码在物理上分开(对于超大型应用程序,可以在目录中甚至在单独的项目中分隔),并在逻辑上独立(使用命名空间)。

典型的应用程序层

在整个文档中,我们参考了以下六个应用程序层的案例研究:

  • 数据层 - 非易失性数据持久性,可能是 SQLite 数据库,但可以使用 XML 文件或任何其他合适的机制实现。
  • 数据访问层 - 数据层的包装器,该层提供数据的创建、读取、更新、删除 (CRUD) 访问权限,而不会向调用方公开实现细节。 例如,DAL 可能包含用于查询或更新数据的 SQL 语句,但引用代码不需要知道这一点。
  • 业务层 -(有时称为业务逻辑层,简称 BLL)包含业务实体定义(模型)和业务逻辑。 业务外观模式的候选项。
  • 服务访问层 - 用于访问云中的服务:从复杂的 Web 服务(REST、JSON、WCF)到从远程服务器轻松检索数据和图像。 封装网络行为,并提供供应用程序和 UI 层使用的简单 API。
  • 应用程序层 - 通常是特定于平台的代码(一般不跨平台共享)或特定于应用程序的代码(一般不可重用)。 想要确定是将代码放在应用程序层还是 UI 层,一个很好的测试方法是:(a) 确定该类是否具有任何实际的显示控件或 (b) 它是否可以在多个屏幕或设备(例如 iPhone 和 iPad)之间共享。
  • 用户界面 (UI) 层 - 面向用户的层,包含屏幕、小组件和管理它们的控制器。

应用程序不一定包含所有层,例如在无法访问网络资源的应用程序中就没有服务访问层。 一个非常简单的应用程序可能会合并数据层和数据访问层,因为操作非常基础。

常见移动软件模式

模式是捕获重复出现的常见问题解决方案的既定方法。 在构建可维护/可理解的移动应用程序时,有几个关键模式非常有用。

  • 模型、视图、视图模型 (MVVM) - 模型-视图-视图模型模式适用于支持数据绑定的框架,例如 Xamarin.Forms。 它由 Windows Presentation Foundation (WPF) 和 Silverlight 等已启用 XAML 的 SDK 推广;其中,视图模型通过数据绑定和命令在数据(模型)和用户界面(视图)之间进行切换。
  • 模型、视图、控制器 (MVC) - 这是一种常见但经常被误解的模式,MVC 在生成用户界面时最常使用,它可以隔离 UI 屏幕(视图)的实际定义、屏幕背后负责处理交互的引擎(控制器)和填充它的数据(模型)。 模型实际上是一个完全可选的部分,因此,理解此模式的核心在于视图和控制器。 MVC 是适用于 iOS 应用程序的常用方法。
  • 业务外观 - AKA 管理器模式,为复杂的工作提供了一个简化的切入点。 例如,在任务跟踪应用程序中,可能有一个具有 GetAllTasks()GetTask(taskID)SaveTask (task) 等方法的 TaskManager 类。TaskManager 类为实际保存/检索任务对象的内部工作提供了一个外观。
  • 单一实例 - 单一实例模式提供了这样一种方式,即,只能存在特定对象的一个实例。 例如,在移动应用程序中使用 SQLite 时,只需要数据库的一个实例。 使用单一实例模式可以很简单地确保这一点。
  • 提供程序 - Microsoft 创造的一种模式(可以说类似于策略或基本依赖关系注入),它鼓励跨 Silverlight、WPF 和 WinForms 应用程序重用代码。 可以针对接口或抽象类编写共享代码,并在使用代码时编写并传入特定于平台的具体实现。
  • 异步 - 不要与 Async 关键字混淆,在需要执行长时间运行的工作而无需保留 UI 或当前处理时可使用异步模式。 在其最简单的形式中,异步模式只是描述长时间运行的任务应在另一个线程(或类似的线程抽象,例如任务)中启动,而当前线程继续处理并侦听后台进程的响应,然后在返回数据和或状态时更新 UI。

每种模式都将进行更详细地说明,案例研究中会介绍它们的实际应用。 维基百科对 MVVMMVC外观单一实例策略提供程序模式(以及一般的设计模式)进行了更详细的描述。