文档章节

Object-base编程

首席吹牛官
 首席吹牛官
发布于 2015/05/22 12:50
字数 915
阅读 1
收藏 0

在C++中,一般的架构设计都是基于多态,基于接口编程。一般的是基类提供接口,子类根据具体的业务逻辑来实现接口,以此来提供程序设计的过程中的可注入性,提高灵活性,但是事实可能不经如此。引入了多态,其实也就是引入了耦合,其强制规定了继承基类和接口的形式,这在整体继承体系中都是不可以更改的。

如下例子:

#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

在main函数中

Dog *dog = new Dog();

	Pet p(dog);
	p.eat();



	Cat *cat = new Cat();

	Pet p1(cat);
	p1.eat();

我们通过多态实现了注入,这就和具体类型和函数形式相关,可是如果现在,我们的eat还是多了个参数Foot,那么我们只有改源码,可以改动eat函数原型,或则在添加一个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是一个底层的操作类,Logic是一个与业务相关的类,work为Logic提供一些底层服务,logic知道work对底层数据的操作。
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,&para));
logic.make();
worker.aMessageComing();
para.para2 += 10;
worker.aMessageComing();
logic.printMessages();
运行结果:

这样可以不改变Work,多引入一个参数,可是却也映入了一个全局的变量,在需要的使用需要改变参数,因为可能我们不知道函数的调用时间,我们需要做随时改变。
这样我们就不需要通过继承完成注入,使用function和bind需要通过对象来完成注入。
不使用继承虚函数使用函数对象可以获得运行时的效率,函数对象可以被inline,提供了性能优化。



本文转载自:http://blog.csdn.net/zhx6044/article/details/38071341

首席吹牛官
粉丝 9
博文 368
码字总数 191938
作品 0
闵行
程序员
私信 提问
在JavaScript面向对象编程中使用继承(4)

大家好像对JavaSript面向对象编程的继承不是很感兴趣哦,都没有什么讨论。也许是大家暂时都遇不到如此复杂的脚本开发solution,不过以后有问题也欢迎来讨论哦。毕竟经典的教程是不可能包括这...

唐玄奘
2017/12/15
0
0
重载(overload)、覆盖(override)、隐藏(hide)的区别

谈谈重载(overload)覆盖(override)与隐藏 转自http://blog.csdn.net/yanjun_1982/archive/2005/09/02/470405.aspx 这三个概念都是与OO中的多态有关系的。如果单是区别重载与覆盖这两个概...

SuShine
2016/05/03
161
0
object sliccing in C++

output:

BruceLinxu
2018/01/15
10
0
Ruby缺失的define_class

Ruby默认提供了等工具用于动态定义实例方法,但貌似没提供动态定义类的方法。 所谓动态定义类,不是指动态创建类,而是指类名是用字符串或符号动态给定的。看完《Ruby元编程》后,我尝试着自...

redraiment
2014/02/20
171
1
AOP的底层实现

原文:http://blog.csdn.net/yzllz001/article/details/54695954 AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础。它是一种面向切面编程的思想。关...

not_in_mountain
2017/10/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
9
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
7
0
【Medium 万赞好文】ViewModel 和 LIveData:模式 + 反模式

原文作者: Jose Alcérreca 原文地址: ViewModels and LiveData: Patterns + AntiPatterns 译者:秉心说 View 和 ViewModel 分配责任 理想情况下,ViewModel 应该对 Android 世界一无所知。...

秉心说
昨天
12
0
重学计算机组成原理(十二) - 异常和中断

1 概览 完好的程序都满足以下特征 自动运行 我们的程序和指令都是一条条顺序执行,不需要通过键盘或者网络给这个程序任何输入 正常运行 没有遇到计算溢出之类的程序错误。 不过,现实的软件世...

JavaEdge
昨天
10
0
程序设计基础(C)第06讲例程

1summing.c /* summing.c -- 根据用户键入的整数求和 */#include <stdio.h>int main(void){ long num; long sum = 0L; /* 把sum 初始化为0 */ int status; p......

树人大学数字媒体吴凡
昨天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部