Before/After クラス

デザインパターンの一つに Before/After パターンというのがあるらしくて、これは Before 処理をしたら After 処理を必ず行うように保証するパターンらしい。


Java ならこんな風に書ける

public void func()
{
    hoge.before();
    try
    {
        doSomething();
    }
    finally
    {
        hoge.after();
    }
}

これなら doSomething で例外が発生しても必ず hoge.after が呼ばれる。


C++ ならこんな風になる。

void func()
{
    hoge.before();
    try
    {
        do_something();
    }
    catch (...)
    {
        hoge.after();
        throw;
    }
    hoge.after();
}

hoge.after を2箇所に書いているのが恐ろしくかっこ悪いのだけれども、finally 節が無いので仕方ない。


ただ、C++ の場合は例外が発生してもデストラクタは必ず呼ばれるので、必ずこういう処理を行うクラスは簡単に用意できる。

struct scoped_before_after
{
    Hoge& hoge_;
    scoped_before_after(Hoge& hoge)
        : hoge_(hoge) { hoge_.before(); }
    ~scoped_before_after() { hoge_.after(); }
};

void func()
{
    scoped_before_after lock(hoge);
    do_something();
}

何度も使うようなパターンであればこれでいいんだけど、一度しか使わないような Before/After ならわざわざ作るのはめんどい。
だからといって同じ文を2度書くのは嫌なので、こんなクラスを作ってみた。

#include <boost/function.hpp>

struct scoped_before_after
{
    boost::function0<void> after_;
    scoped_before_after(const boost::function0<void>& after)
        : after_(after) { }
    scoped_before_after(const boost::function0<void>& before, const boost::function0<void>& after)
        : after_(after) { before(); }
    ~scoped_before_after() { after_(); }
};

これはこんな風に使う。

#include <boost/lambda/lambda.hpp>
#include "scoped_before_after.h"

struct fuga
{
    int value_ = 0;

    void func()
    {
        using namespace boost::lambda;
        scoped_before_after(var(value_) += 1, var(value_) -= 1);
        do_something();
    }
};

このように、特にクラス化する必要すら感じられない Before/After 処理を書く場合は使えるかもしれない。

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy