通过这段时间的思考,经过实际编码的验证,总结了一下几条设计技巧,记录备忘。
在模块设计中,模块内部的运行信息通过回调的形式,给模块外部调用者提供查询模块运行状态的手段。最常见用途的可能就是运行日志了。回调函数是个好东西,在C/C++里叫做函数指针,在.net里叫做事件。
这种模块内部的暴露只是暴露运行信息,而不要把内部成员暴露出来,否则就与模块的低耦合(类的封装)相违背了。
以C#为例:
using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { A a = new A(); a.log += a_log; a.Test(); } static void a_log(object sender, string e) { Console.WriteLine(DateTime.Now.ToString("u") + " " + e); } } class A { public event EventHandler<String> log; private void OnLog(String msg) { if (log != null) { log(this, msg); } } public void Test() { OnLog("begin do something..."); //do something OnLog("done."); } } }
为了让界面和功能分离,UI不要直接控制程序的运行状态,而是要在UI和程序状态之间加入一个配置文件层。即
UI-----配置文件------程序初始状态
配置文件一般都采用xml格式。这样就需要制定xml配置文件的规范,有了这个规范,UI和程序设计就可以独立进行了。当然一开始,往往不太容易很明确的确定配置文件规范,需要一个迭代的过程。
这样做带来的好处是显而易见的,最明显的就是程序的可移植性。因为移植最难的地方也就是UI了,既然UI与程序本身没有直接联系了,所以移植非常简单。
要做到这种分离方式,必须保证配置文件的规范性。一旦这个规范修改了,UI和程序都需要相应的修改。
伪代码如下:
// 功能类 class A { private String filePath; //配置文件路径 public static A FromXml(); //从xml配置文件初始化功能模块 } //界面类 class UI { private String filePath; //配置文件路径 public void FromXml(); //从xml配置文件初始化UI public void ToXml(); //保存当前UI配置为配置文件 }