zoukankan      html  css  js  c++  java
  • 使用function改进设计

      我们假设这样一种应用场景,有两个类A和B,在B中需要调用A的一个方法(成员函数)。那么我们的代码可能是这个样子的:

    class A
    {
    public:
    	void Func(void) 
    	{ 
    		printf("%s\r\n", __FUNCTION__); 
    	}
    };
    
    class B
    {
    public:
    	void UseA() 
    	{ 
    		a->Func(); 
    	}
    
    public:
    	A* a;
    };
    

      调用代码是这样的:

    A a;
    B b;
    b.a = &a;
    b.UseA();
    

      我们观察上面的代码,看看有什么问题:

    1. 两个类中B对A产生了一个依赖关系,这让人有点不爽;
    2. 哪天我们想用另外一个类C替代A的作用意味着我们要重写B,这让人更不爽;
      上面两个问题实质上是耦合的问题,依赖关系是强耦合,耦合度高了代码可读性和可维护性都会变差。
     
      我们分析一下这两个类的关系,在B中调用了A的一个成员函数所以产生了依赖。而这个调用完全可以使用函数指针,由于C++的函数指针使用起来太过麻烦,所以我们用function代替。改进后的B的定义如下:
    class B
    {
    public:
    	std::function<void(void)>	AFunc;
    
    	void UseA(void) 
    	{ 
    		if(AFunc != NULL) AFunc(); 
    	}
    };
    
     
    调用方法和之前差不多,只是把赋值操作的对象由A的指针改成了A的成员函数:
    A a;
    B b;
    b.AFunc = std::bind(&A::Func, &a);
    b.UseA();
    
      
      代码看起来复杂了那么一点点,但是从代码逻辑的角度看改进了很多:
    1. B和A彻底解耦,只在运行期才B的某个对象对A的某个对象产生依赖,而且这种依赖完全在调用者的控制之下;
    2. 我们想把A替换成C,那么就换把,改一下调用代码就可以搞定,B的定义代码一行不动——这正是我们追求的灵活性和扩展性;
    C c;
    b.AFunc = std::bind(&C::Func, &c);
    b.UseA();
    
     
      
      作为C++ 0x的新特性,std::function和std::bind目前只在VS2010中才被支持,用其他编译器的同学可以用boost库作为替代方案,用法完全相同。
    作者:小时了了
    原创文章,欢迎转载,但请以链接形式注明本文地址.
  • 相关阅读:
    Insus Meta Utility
    The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
    Insus Binary Utility
    asp.net实现文件下载功能
    Column 'Column Name' does not belong to table Table
    程序已被编译为DLL,怎样去修改程序功能
    如何在Web网站实现搜索功能
    如何把数据流转换为二进制字符串
    Asp.net更新文件夹的文件
    如何显示中文月份
  • 原文地址:https://www.cnblogs.com/xrunning/p/1897575.html
Copyright © 2011-2022 走看看