一、C++的诟病
C++最遭人诟病的地方就是定义一个类需要写两个文件,一个.h文件和一个.cpp文件。例如定义一个CMainFrame类,mainframe.h内容如下:
class CMainFrame : public CFrameWndEx { protected: CMainFrame(); public: virtual ~CMainFrame(); };
mainframe.cpp内容如下:
CMainFrame::CMainFrame() { } CMainFrame::~CMainFrame() { }
当需要给这个类添加一个方法时,需要同时修改.h文件和.cpp文件。例如新增一个DefWindowProc函数。需要在.h文件中增加该函数的声明。
class CMainFrame : public CFrameWndEx { protected: CMainFrame(); public: virtual ~CMainFrame(); protected: virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam); };
mainframe.cpp中增加DefWindowProc的定义:
LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if(message==WM_NCPAINT ) { if(bShow){ ShowWindow(SW_SHOW); } else { ShowWindow(SW_HIDE); } } return CFrameWndEx::DefWindowProc(message, wParam, lParam); }
可以看出C++的类定义代码中,一次变化需要修改两个文件,其维护的繁琐令人诟病。
二、Java的改进
然而Java的出现彻底解决了这个问题,一个类就对应一个.java文件(包括后来其他面向对象语言也秉承了这个思路,比如C#)。
比如一个LogService类用于对日志进行维护,起初只包含日志的增删功能,LogService.java代码如下。
public class LogService{ public ServiceResult<Boolean> addLog (SysLogInfo logInfo) { ...... } public ServiceResult<Boolean> delLog (String id) { ...... } }
当需要增加一个updateLog方法时,仅需对LogService.java进行修改。
public class LogService{ public ServiceResult<Boolean> addLog (SysLogInfo logInfo) { ...... } public ServiceResult<Boolean> delLog(String id) { ...... } public ServiceResult<Boolean> updateLog (SysLogInfo logInfo) { ...... } }
一切变得方便了很多。
三、误用导致的退步
但是最近在看一些基于Spring(SpringBoot、SpringMVC)框架写的代码时,发现很多类的代码又回到了C++的形式。例如在使用一个LogService时,开发人员首先定义了一个interface,在LogService.java中:
public interfac<strong style="color:transparent">本文来源gaodai#ma#com搞@@代~&码网^</strong>e LogService { ServiceResult<Boolean> addLog(SysLogInfo logInfo); ServiceResult<Boolean> delLog(String id); }
然后定义了一个该接口的实现类,在LogServiceImpl.java中:
public class LogServiceImpl implements LogService{ @Override public ServiceResult<Boolean> addLog(SysLogInfo logInfo) { ...... } @Override public ServiceResult<Boolean> delLog(String id) { ...... } }
在需要实例化这个类的地方用了一个@Autowired注解注入。
public class LogController { @Autowired private LogService logservice; }
在问及开发人员为什么要象这样做时,其给了一个自信的回答:这是面向接口编程!
注意:这个设计中LogService.java类似于C++中的.h文件,LogServiceImpl.java类似于C++中的.cpp文件,这两个文件共同定义了一个LogService类。当需要给这个类添加一个updateLog方法时,LogService.java和LogServiceImpl.java都需要被修改,又走回了C++的老路。这显然是对面向接口编程的曲解。如果这样都能算面向接口编程的话,那么C++就成了一门天然的面向接口编程的语言,还何必去学那些复杂的设计模式。