在C++中,通常的架構設計都是基於多態,基於接口編程。通常的是基類提供接口,子類根據具體的業務邏輯來實現接口,以此來提供程序設計的過程當中的可注入性,提升靈活性,可是事實可能不經如此。引入了多態,其實也就是引入了耦合,其強制規定了繼承基類和接口的形式,這在總體繼承體系中都是不能夠更改的。ios
以下例子:編程
#ifndef ANIMAL_H #define ANIMAL_H #include <iostream> class Animal { public: virtual void eat() = 0; virtual ~Animal() = 0; }; Animal::~Animal() { } class Dog : public Animal { public: void eat() { std::cout << "DOG EAT MEAT!\n"; } ~Dog() {} }; class Cat : public Animal { public: void eat() { std::cout << "CAT EAT FISH!\n"; } ~Cat() {} }; class Pet { public: Pet(Animal *_a) : _aAnimal(_a) { }
~Pet()
{
delete _aAnimal;
} void eat() { _aAnimal->eat(); } private: Animal *_aAnimal; }; #endif // ANIMAL_H
Dog *dog = new Dog(); Pet p(dog); p.eat(); Cat *cat = new Cat(); Pet p1(cat); p1.eat();
C++0x中的bind函數和function模板類爲咱們提供了很好的設計解決方案,提供多態基於函數對象,其只和函數的返回值和參數有關。陳碩老師稱其爲Object-base編程,經過對象來完成功能注入。拳拳到肉(陳老師原話)。關於bind和function不清楚的能夠先了解下,這邊就不贅述了。性能優化
看這個例子:架構
#include <iostream> #include <functional> #include <list> class Work { public: typedef std::function<void ()> doAmessage; void registerDoMessage(const doAmessage &f) { _aAmessage = f; } void do_aTask() { std::cout << "DO A TASK!\n"; } void aMessageComing() { _aAmessage(); } private: doAmessage _aAmessage; }; class Logic { public: typedef std::function<void ()> doTaskCallBack; Logic(const doTaskCallBack &f) : _dtask(f) { } void make() { _dtask(); } void aMessageComing() { _messageList.push_back("A TASK!"); } void printMessages() { for (auto ite = _messageList.begin(); ite != _messageList.end(); ++ite) { std::cout << (*ite).data() << '\n'; } } private: doTaskCallBack _dtask; std::list<std::string> _messageList; }; int main() { //std::cout << "Hello World\n"; Work worker; Logic logic(std::bind(&Work::do_aTask,worker)); worker.registerDoMessage(std::bind(&Logic::aMessageComing,&logic)); logic.make(); worker.aMessageComing(); worker.aMessageComing(); logic.printMessages(); return 0; }
Work::do_aTask爲Logic提供服務,在Logic::make中調用,在
Logic logic(std::bind(&Work::do_aTask,worker)); 這句完成了注入操做。
Work::aMessageComing,須要Logic提供的具體的邏輯,在worker.registerDoMessage(std::bind(&Logic::aMessageComing,&logic));
完成了注入。
若是如今我定義了一個class,其只用提供一個void xxx()成員函數,那就能夠直接綁定給Work使用。函數
能夠注意到個人回調對象都是性能
std::function<void ()>
爲何,我是想在提供一些變化。
好比,Logic的aMessageComing(Parameter *_p)函數添加了一個函數,我但願Work不須要改變,這就須要一個參數,使用對象來實現對參數的保存。定義以下:struct Parameter { Parameter() : para1(0), para2(0) { } int para1; int para2; };使用以下:Parameter para; Work worker; Logic logic(std::bind(&Work::do_aTask,worker)); worker.registerDoMessage(std::bind(&Logic::aMessageComing,&logic,¶)); logic.make(); worker.aMessageComing(); para.para2 += 10; worker.aMessageComing(); logic.printMessages();運行結果:這樣能夠不改變Work,多引入一個參數,但是卻也映入了一個全局的變量,在須要的使用須要改變參數,由於可能咱們不知道函數的調用時間,咱們須要作隨時改變。這樣咱們就不須要經過繼承完成注入,使用function和bind須要經過對象來完成注入。不使用繼承虛函數使用函數對象能夠得到運行時的效率,函數對象能夠被inline,提供了性能優化。