Rug*_*rra 8 c++ design-patterns decorator
大多数人都知道装饰图案的披萨/咖啡示例.
Pizza* pizza1 = BigPizzaDecorator(MushromDecorator(SimplePizza()));
Pizza* pizza2 = MushromDecorator(BigPizzaDecorator(SimplePizza()));
Run Code Online (Sandbox Code Playgroud)
这两个对象的行为方式类似,但并非完全,特别是如果您具有非交换操作,例如:
BigPizzaDecorator::price() { return 10 + PizzaDecorator::price(); } // this is commutative
BigPizzaDecorator::name() { return "big " + PizzaDecorator::name(); } // this is not commutative
Run Code Online (Sandbox Code Playgroud)
所以价格pizza1和pizza2是相同的,但名称不是,例如第一个应该是"Big mushroom pizza",第二个"Mushroom big pizza".第一个是英语正确(可能更好的是"蘑菇大披萨",但它并不那么重要).
"Head first"一书通过Cofee示例指出了这个问题:
当您需要在装饰器链中查看多个图层时,您开始将装饰器推到其真实意图之外.
然而,这样的事情是可能的.想象一下CondimentPrettyPrint装饰器解析最终的解释,可以打印"Mocha,Whip,Mocha"作为"Whip,Double Mocha".
最好的方法是什么?(operator<?)
我一直都不知道使用装饰器时需要这种东西.而且我认为如果你需要这样做,那么你就不应该使用装饰器,特别是当你故意"推动装饰器超出它的意图"时.
我这样做了,代码如下.基本上,我在SimplePizza对象周围创建一个薄层,了解装饰器需要什么,然后装饰器装饰它.
这里的主要问题是,为了维持输出中的顺序,你必须维持装饰器之间的关系 - 这很快就会成为维护的噩梦.
#include <iostream>
#include <queue>
#include <sstream>
struct name_part
{
std::string mName;
int mPriority;
name_part(const std::string& name, int priority)
: mName(name)
, mPriority(priority)
{
}
};
bool operator<(const name_part& a, const name_part& b)
{
return (a.mPriority < b.mPriority);
}
std::string priority_queueToString(const std::priority_queue<name_part>& orig)
{
std::ostringstream oss;
std::priority_queue<name_part> q(orig);
while (!q.empty())
{
oss << q.top().mName << " ";
q.pop();
}
return oss.str();
}
struct SimplePizza
{
virtual std::string name()
{
return "pizza";
}
};
struct SimplePizzaImplementer : SimplePizza
{
SimplePizza *mDecorated;
SimplePizzaImplementer()
: mDecorated(0)
{
}
SimplePizzaImplementer(SimplePizza *decorated)
: mDecorated(decorated)
{
}
virtual std::string name()
{
return priority_queueToString(nameParts());
}
virtual std::priority_queue<name_part> nameParts()
{
std::priority_queue<name_part> q;
if (mDecorated)
{
q.push(name_part(mDecorated->name(), 0));
}
return q;
}
};
struct MushroomDecorator : SimplePizzaImplementer
{
SimplePizzaImplementer *mDecorated;
MushroomDecorator(SimplePizzaImplementer *decorated)
: mDecorated(decorated)
{
}
virtual std::string name()
{
return priority_queueToString(nameParts());
}
virtual std::priority_queue<name_part> nameParts()
{
std::priority_queue<name_part> q = mDecorated->nameParts();
q.push(name_part("mushroom", 1));
return q;
}
};
struct BigDecorator : SimplePizzaImplementer
{
SimplePizzaImplementer *mDecorated;
BigDecorator(SimplePizzaImplementer *decorated)
: mDecorated(decorated)
{
}
virtual std::string name()
{
return priority_queueToString(nameParts());
}
virtual std::priority_queue<name_part> nameParts()
{
std::priority_queue<name_part> q = mDecorated->nameParts();
q.push(name_part("big", 2));
return q;
}
};
int main()
{
SimplePizzaImplementer *impl = new SimplePizzaImplementer(new SimplePizza());
SimplePizza *pizza1 = new MushroomDecorator(new BigDecorator(impl));
SimplePizza *pizza2 = new BigDecorator(new MushroomDecorator(impl));
std::cout << pizza1->name() << std::endl;
std::cout << pizza2->name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1121 次 |
| 最近记录: |