面向方法、宏定义、dll库、面向对象给程序灵活性带来的好处
2013-10-25 14:23
274 查看
从一个网上找的例子说起:
定义了一个ILog接口,用于记录日志文件,它有一个对外接口WriteLog用于记录日志
这些日志可以记录到磁盘上(FileLog)或者数据库上(DBLog),或者其它的什么地方;后来,你又发现需要一个StdOutLog,于是你又继承了一个StdOutLog类。
各种派生类:DBLog, FileLog, StdOutLog不同的Log创建不同的对象。但对于程序来说他们都是ILog,程序中使用该日志功能的方法都是ILog->WriteLog(),对于日志类的不同具体实现不影响你客户端的已有代码。
版本一
1、如果我们用面向过程的方法,直接针对不同的实现都分别写一个write函数,eg:void write_dblog()
2、接着,用户要求改用文件来实现,你又得写一个write_filelog()函数,关键是接下来你得把客户端程序中所有调用write_dblog的代码都改成write_filelog()
3、对于write_stdoutlog同样是上面的问题
版本二
这下,我们感觉相当的不爽,改成用宏定义来实现
#define write_log write_stdoutlog
好了,以后再怎么改,我们的程序只需要修改宏就好了。
版本三
过了一段时间,用户老是要频繁的修改记录方式,每次修改宏定义后,我们又要重新编译,
为了避免重新编译,我们现在改用dll。我们把不同写日志的函数都叫做 write_log,然后不同的dll(db.dll,file.dll,stdout.dll)根据不同需要去实现write_log函数
最后,我们把write_log 这个函数导出。这样以来,每次用户要更改记录方式的时候,我们可以直接根据需要去替换这个dll库,而不用重新修改甚至重新编译用户的代码。
(感叹dll的神奇和伟大)
版本四:
又过了一段时间,用户又提出了许多需求, 我们把他们叫做:function1(),function2(),function3()......function100()
这下麻烦了,由于使用dll,我们需要导出dll中的函数,并用指向函数的指针来记录他们,100个需求对应100个函数,都要我们在用户程序中用指针的方式记录下来,对于这个工作量 我只能表示"呵呵"。
好了,接着改。用面向对象的方法来解决:
创建一个接口
class ILog
{
virtual void write_log() = 0;
virtual void function1() = 0;
virtual void function2() = 0;
...
virtual void function100() = 0;
};
然后在DB.dll和 File.dll中,实现这个接口
class DBLog : public ILog
{
virtual void write_log() {.....};
virtual void function1() {...};
virtual void function2() {...};
...
virtual void function100() {.....};
};
class FileLog : public ILog
{
virtual void write_log() {.....};
virtual void function1() {...};
virtual void function2() {...};
...
virtual void function100() {.....};
};
最后,你再让这些dll文件只导出一个获取具体实现类的接口: ILog * create_log_object();
,这样用户程序里只需要保存一个,ILog * pLog 类型的指针。
其他的地方只需要写pLog->write_log() 、pLog->function1() 。。。。。,看到没有这样用户代码段里就不需要再去记录100多个函数指针了。我们程序的灵活性进一步提高!!!!!
定义了一个ILog接口,用于记录日志文件,它有一个对外接口WriteLog用于记录日志
这些日志可以记录到磁盘上(FileLog)或者数据库上(DBLog),或者其它的什么地方;后来,你又发现需要一个StdOutLog,于是你又继承了一个StdOutLog类。
各种派生类:DBLog, FileLog, StdOutLog不同的Log创建不同的对象。但对于程序来说他们都是ILog,程序中使用该日志功能的方法都是ILog->WriteLog(),对于日志类的不同具体实现不影响你客户端的已有代码。
版本一
1、如果我们用面向过程的方法,直接针对不同的实现都分别写一个write函数,eg:void write_dblog()
2、接着,用户要求改用文件来实现,你又得写一个write_filelog()函数,关键是接下来你得把客户端程序中所有调用write_dblog的代码都改成write_filelog()
3、对于write_stdoutlog同样是上面的问题
版本二
这下,我们感觉相当的不爽,改成用宏定义来实现
#define write_log write_stdoutlog
好了,以后再怎么改,我们的程序只需要修改宏就好了。
版本三
过了一段时间,用户老是要频繁的修改记录方式,每次修改宏定义后,我们又要重新编译,
为了避免重新编译,我们现在改用dll。我们把不同写日志的函数都叫做 write_log,然后不同的dll(db.dll,file.dll,stdout.dll)根据不同需要去实现write_log函数
最后,我们把write_log 这个函数导出。这样以来,每次用户要更改记录方式的时候,我们可以直接根据需要去替换这个dll库,而不用重新修改甚至重新编译用户的代码。
(感叹dll的神奇和伟大)
版本四:
又过了一段时间,用户又提出了许多需求, 我们把他们叫做:function1(),function2(),function3()......function100()
这下麻烦了,由于使用dll,我们需要导出dll中的函数,并用指向函数的指针来记录他们,100个需求对应100个函数,都要我们在用户程序中用指针的方式记录下来,对于这个工作量 我只能表示"呵呵"。
好了,接着改。用面向对象的方法来解决:
创建一个接口
class ILog
{
virtual void write_log() = 0;
virtual void function1() = 0;
virtual void function2() = 0;
...
virtual void function100() = 0;
};
然后在DB.dll和 File.dll中,实现这个接口
class DBLog : public ILog
{
virtual void write_log() {.....};
virtual void function1() {...};
virtual void function2() {...};
...
virtual void function100() {.....};
};
class FileLog : public ILog
{
virtual void write_log() {.....};
virtual void function1() {...};
virtual void function2() {...};
...
virtual void function100() {.....};
};
最后,你再让这些dll文件只导出一个获取具体实现类的接口: ILog * create_log_object();
,这样用户程序里只需要保存一个,ILog * pLog 类型的指针。
其他的地方只需要写pLog->write_log() 、pLog->function1() 。。。。。,看到没有这样用户代码段里就不需要再去记录100多个函数指针了。我们程序的灵活性进一步提高!!!!!
相关文章推荐
- 面向对象之构造函数(可让程序运行前初始化一些东西)、函数(方法)重载
- 对象和数据库的天然阻抗(越抽象越灵活(容易变化,变化带来的损失小)越具体越固定(不易变化,变化带来的影响范围广损失大)) 【面向对象在方法上与面向过程对立,在数据存储上与关系型数据对立,抽象与具体】
- 面向对象建模与数据库建模两种分析设计方法的比较
- java 面向对象基础 UML图 构造方法 对象 参数传值 关联关系 依赖关系
- php面向对象中static静态属性和静态方法的调用
- 转载:面向对象语言中实现多态方法
- 使用GCJ编译Java程序供Matlab调用Java对象方法实践
- 从程序分析线程获得的是对象锁还是对象的方法锁?
- 测试面向对象软件时,设计集成测试用例的方法
- 面向对象建模与数据库建模两种分析设计方法的比较(转载)
- 用比较的方法认识PHP的面向对象
- 面向对象设计6大原则之五(接口隔离原则)-系统有更高的灵活性
- 面向对象第九课,面向对象三大基本特征,继承,Object用法,toString和equals方法
- 再探结构化设计和面向对象设计方法
- 面向对象特征及其好处与缺点
- 面向对象概念:字段、属性和方法
- Php面向对象魔术方法总结
- Java中类与对象 面向对象 对象的方法属性 构造方法(持续更新Ing)
- Java之面向对象例子(三) 多态,重写,重载,equals()方法和toString()方法的重写
- 面向对象 方法的调用 汽车速度加减