Object-base编程

在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,提供了性能优化。





Object-base编程,布布扣,bubuko.com

时间: 2024-08-07 00:07:51

Object-base编程的相关文章

[Object]面向对象编程(自己总结版)

[Object]面向对象编程(自己总结版) 2014-06-06 面向对象编程 感受:原理javascript也可以用完全面向对象的方式编程,兴奋得一个晚上都没睡好觉. 有种越深入越想编程的状态,有种上瘾的快感. 1,面向对象方式编程 Js代码   function Aa(){ //属性设置 this.property1:value1,//例如this.nameinput = $("input['name'=name]"); this.property2:value2, this.pr

[Object]面向对象编程(高程版)(0)属性和方法

[Object]面向对象编程(高程版)(0)属性和方法 博客分类: Web前端-JS语言核心 私有变量成员变量公有变量静态变量 zccst转载+原创 Js代码   function Person(){ var private_name = "小明"; //私有属性 var private_age = 10;      //私有属性 this.privilege_name = "小红"; //特权属性 this.privilege_age = 9;       //特

再谈javascript面向对象编程

前言:虽有陈皓<Javascript 面向对象编程>珠玉在前,但是我还是忍不住再画蛇添足的补上一篇文章,主要是因为javascript这门语言魅力.另外这篇文章是一篇入门文章,我也是才开始学习Javascript,有一点心得,才想写一篇这样文章,文章中难免有错误的地方,还请各位不吝吐槽指正 吐槽Javascript 初次接触Javascript,这门语言的确会让很多正规军感到诸多的不适,这种不适来自于Javascript的语法的简练和不严谨,这种不适也 来自Javascript这个悲催的名称,

Web3D编程入门总结——面向对象的基础Web3D框架

本篇主要通过分析Tony Parisi的sim.js库(原版代码托管于:https://github.com/tparisi/WebGLBook/tree/master/sim),总结基础Web3D框架的编写方法.在上一篇的基础上,要求读者具有简短英文阅读或者查字典的能力. 限于水平和时间,本文难免出现错误与遗漏,您在阅读过程中如果遇到错误或者疑问请在评论区中指出,我将尽快回复. 为提高JavaScript编程效率,建议使用WebStorm工具进行网页程序编写,WebStorm官网:http:/

1.JAVA 编程思想——对象入门

对象入门 欢迎转载,转载请标明出处:    http://blog.csdn.net/notbaron/article/details/51040219 如果学JAVA,没有读透<JAVA 编程思想>这本书,实在不好意思和别人说自己学过JAVA.鉴于此,蛤蟆忙里偷闲,偷偷翻看这本传说中的牛书. 面向对象编程OOP具有多方面吸引力.实现了更快和更廉价的开发与维护过程.对分析与设计人员,建模处理变得更加简单,能生成清晰.已于维护的设计方案. 这些描述看上去非常吸引人的,不过蛤蟆还是没啥印象(至少到

python高级编程之选择好名称:pepe8和命名最佳实践

# # -*- coding: utf-8 -*- # # python:2.x # __author__ = 'Administrator' # my_list=['a','b','c','d'] # """ # 大部分标准程序加在构建时都不会忽略可用性,看下面的例子理解下这句话的含义 # """ # if 'e' not in my_list: #     my_list.append('e') # print my_list # #['a'

使用腾讯云 GPU 学习深度学习系列之二:Tensorflow 简明原理【转】

转自:https://www.qcloud.com/community/article/598765?fromSource=gwzcw.117333.117333.117333 这是<使用腾讯云 GPU 学习深度学习>系列文章的第二篇,主要介绍了 Tensorflow 的原理,以及如何用最简单的Python代码进行功能实现.本系列文章主要介绍如何使用 腾讯云GPU服务器 进行深度学习运算,前面主要介绍原理部分,后期则以实践为主. 往期内容: 使用腾讯云 GPU 学习深度学习系列之一:传统机器学

python简易web服务器学习笔记(三)

import sys, os, BaseHTTPServer #------------------------------------------------------------------------------- class ServerException(Exception): '''For internal error reporting.''' pass #--------------------------------------------------------------

R︱并行计算以及提高运算效率的方式(parallel包、clusterExport函数、foreach包、SupR包等)

终于开始攻克并行这一块了,有点小兴奋,来看看网络上R语言并行办法有哪些: 赵鹏老师(R与并行计算)做的总结已经很到位.现在并行可以分为:  隐式并行:隐式计算对用户隐藏了大部分细节,用户不需要知道具体数据分配方式 ,算法的实现或者底层的硬件资源分配.系统会根据当前的硬件资源来自动启动计算核心.显然,这种模式对于大多数用户来说是最喜闻乐见的. 显性并行:显式计算则要求用户能够自己处理算例中数据划分,任务分配,计算以及最后的结果收集.因此,显式计算模式对用户的要求更高,用户不仅需要理解自己的算法,还

Chromium扩展(Extension)的Content Script加载过程分析

Chromium的Extension由Page和Content Script组成.Page有UI和JS,它们加载在自己的Extension Process中渲染和执行.Content Script只有JS,这些JS是注入在宿主网页中执行的.Content Script可以访问宿主网页的DOM Tree,从而可以增强宿主网页的功能.本文接下来分析Content Script注入到宿主网页执行的过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 我们可以在