読者です 読者をやめる 読者になる 読者になる

Decolator, Mix-Inのような継承関係

c++

Decolatorパターンの場合、内部で持っているコンポーネントの振る舞いが分かりにくい。Mix-Inの場合、プロパティとなるClassがtemplate classとなってしまって、複雑になる。

そこで、状況によってはあ下記のような継承もありかな。

  • RuleBaseはルール f : double -> doubleを複数保持する。
  • RuleBase::apply(double x)は、登録された順にルールをxに適用する。
  • RuleAは、ルールx + 1.0をRuleBaseに登録する。
  • RuleBは、ルールx * 3.0をRuleBaseに登録する。
  • Cは、RuleAとRuleBを持っている。継承の順番にRuleBaseに登録する。
class RuleBase {
public:
	RuleBase()  {
	}
	virtual ~RuleBase() {}
	void addRule(const std::function<double(double)>& f)
	{
		_f.push_back(f);
	}
	double apply(double x) const 
	{ 
		for (auto& f : _f) { x = f(x); }
		return x;
	}
private:
	std::list<std::function<double(double)> > _f;
};

class RuleA : virtual RuleBase {
public:
	RuleA()
	{
		addRule([&](double x) {return rule(x); });
	}
	virtual ~RuleA() {}
private:
	double rule(double x) const { return x + 1.0; }
};

class RuleB : virtual RuleBase {
public:
	RuleB()
	{
		addRule([&](double x) {return rule(x); });
	}
	virtual ~RuleB() {}
private:
	double rule(double x) const { return x * 3.0; }
};

class C : RuleA, RuleB, virtual RuleBase
{
public:
	C() {}
	double get(double x) const { return RuleBase::apply(x); }
};

int main()
{
	C c;
	std::cout << c.get(0.5) << std::endl; // (0.5 + 1.0) * 3.0
    return 0;
}