作者:吴香伟 发表于 2014/09/12

版权声明:可以任意转载,转载时务必以超链接形式标明文章原始出处和作者信息以及版权声明

Ceph实现中使用了大量派生于Context抽象类的子类,用法简单却很巧妙,我将它称为Context模式或者上下文模式。上下文模式像极了C的回调函数,而回调函数又像极了Template模式,但Template模式和Context模式似乎有所不同。

回调函数的使用场景是,函数的实现者不知道何时调用函数,而函数的调用者不知道如何实现函数。回调的实现者实现由调用者提供的函数接口,并将其注册给调用者。调用者在适当的时机调用函数完成实现者指定的功能。

从“你不用调用我,让我调用你”的角度看,Template模式是ODD中的回调函数。Template模式中,父类充当回调中的调用者角色,子类充当实现者角色。一般地,父类定义了程序的主要逻辑功能,而子类只用于填充逻辑中不稳定或者可以多样化的部分,这部分的内容通过多态机制来调用。

Template模式中一个很重要的因素是,调用者父类和实现者子类共享同一个上下文信息。但是,如果父类是重量级的并且子类实现回调接口使用的上下文内容同父类的上下文风马牛不相及时,就有必要将二者分离。回头看,C的回调和Template模式之间的区别:C回调的调用者和实现者是属于两个实体的,而Template模式将实现者和调用者放到了一个实体中。Context模式又从Template模式中将这两者分离开来

class Context {
protected:
virtual void finish(int r) = 0; /// 派生类实现接口 public:
virtual void complete(int r) { /// 调用者调用接口,函数执行结束后销毁对象
finish(r); /// r用于让子类判断是否执行,r为0时执行,不为0时放弃执行
delete this;
}
};

从上文的分析可知,Context模式和Template模式的区别是,调用者和实现者是否共享上下文信息。Context类将实现者的上下文信息封装在子类中,提供给调用者void complete(int r)方法并且授予其是否执行回调的权利。因为将实现者的上下文信息封装在子类,因此可以不必像C回调那样设计各种不同的回调函数类型,从而统一了所有的回调接口。

class C_SafeCond : public Context {
bool *done; /// true after finish() has been called
public:
C_SafeCond(bool *d ) : done(d) { /// 主要这里引用的是done的地址
*done = false;
}
void finish(int r) { /// 执行complete后,设置done为true。
*done = true;
}
} /// 从远程OSD中同步读取Object数据
int librados::IoCtxImpl::operate_read(const object_t& oid, ::ObjectOperation *o, bufferlist *pbl, int flags)
{
bool done; Context *onack = new C_SafeCond(&mylock, &cond, &done, &r); Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc, *o, snap_seq, pbl, flags, onack, &ver);
objecter->op_submit(objecter_op); /// 发送读object请求,收到对该请求的回复后,执行onack回调 while (!done){ /// 线程阻塞直到onack被执行
cond.Wait(mylock);
} return r;
}

通常情况下,Context模式适用于异步执行环境。但上面的例子说明,它也可以用于实现同步等待。

设计模式:Context模式的更多相关文章

  1. [Head First设计模式]生活中学设计模式——状态模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  2. 关于 "Context" 模式(基于COM思想IUnknown思想)

    有同事很喜欢用Context模式,觉得是自己"首创", 我有些自己的想法, 或者大家可以发表下自己的观点.   什么是Context模式? 23种设计模式中没有这个模式, 是同事自 ...

  3. linkin大话设计模式--策略模式

    linkin大话设计模式--策略模式 Strategy [ˈstrætədʒi]  策略 策略模式用于封装系列的算法,这些算法通常被封装在一个称为Context的类中,客户端程序可以自由的选择任何一种 ...

  4. Java设计模式----解释器模式

    计算器中,我们输入“20 + 10 - 5”,计算器会得出结果25并返回给我们.可你有没有想过计算器是怎样完成四则运算的?或者说,计算器是怎样识别你输入的这串字符串信息,并加以解析,然后执行之,得出结 ...

  5. C#设计模式--状态模式

    设计模式: 状态模式(State Pattern) 简单介绍: 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示 ...

  6. 【转】Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式

    [转]Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式 博客分类: 企业应用面临的问题 java并发编程 Struts2的线程安全ThreadLocal模式St ...

  7. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  8. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  9. [Head First设计模式]抢票中的设计模式——代理模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

随机推荐

  1. 关于移动端常用的盒模型与flex布局

    在移动端选择布局的方式中常用盒模型display:-webkit-box达到自适应,然而display:-webkit-flex也同样能达到效果,因自在己移动端用-webkit-box比felx方式熟 ...

  2. 36、重新复习html和css之二

    (1)由于公司是意大利的网段, (2)而且公司的电脑是保密的, (3)文件发不出去, (4)U盘插不进去. (5)而且我们组的项目整体上已经开发完毕,客户暂时没有什么大的需求, 所以如果我不把这些技术 ...

  3. 动态设置和访问cxgrid列的Properties(转)

    原文:http://www.cnblogs.com/hnxxcxg/archive/2010/05/24/2940711.html 动态设置和访问cxgrid列的Properties 设置: cxGr ...

  4. PHP简单利用token防止表单重复提交

    <?php /* * PHP简单利用token防止表单重复提交 * 此处理方法纯粹是为了给初学者参考 */ session_start(); function set_token() { $_S ...

  5. mysql的多实例安装

    单机多实例据说可以最大程度提高硬件使用,谁知道呢,但是以前的公司喜欢这样搞,我最近也在学习复制什么的,电脑搞不起两台虚拟机,刚好单机多实例可以解救我.下面就说说步骤. 承上文http://www.cn ...

  6. HDOJ(1348)二维凸包

    Wall http://acm.hdu.edu.cn/showproblem.php?pid=1348 题目描述:有个国王想在他的城堡外面修围墙,围墙与城堡的最小距离为L,要求围墙长度最短.求围墙的长 ...

  7. 1-12 ARP协议

    ARP(Address Resolution Protocol)地址解析协议,负责将相应的IP地址解析成MAC地址. 在局域网中,网络中实际传输的是‘帧’,帧里面包含了目的主机的MAC.ARP就是用来 ...

  8. CSS深入研究:display的恐怖故事解密(2) - table-cell

    上集<CSS深入研究:display的恐怖故事解密(1) - display-inline>已经把display的属性列表拉出来溜了,发现在这个属性恐怖面貌其实都是脆弱的伪装.除了部分常用 ...

  9. 学习C:程序

    #include <stdio.h> main(){ /*将输入复制到输出,并将其中连续的多个空格用一个空格代替*/ int c,nb; nb = 0; while((c = getcha ...

  10. centos7安装mariadb10遇到的问题解决

    4. 安装中的错误 4.1 /bin/ld: cannot find -lz /bin/ld: cannot find -lzcollect2: error: ld returned 1 exit s ...