使用装饰模式的观察者模式
我想制定一个程序来完成饮料订单输入系统。 (我可能会做描述,成本)
我想使用装饰者模式和观察者模式。 我制作了UML图纸并将其保存为图片以便于查看。 本网站不会让我作为word文档上传,所以我必须上传图片 - 我希望它可以轻松查看....
在进入编码部分之前,我需要知道我是否正确地完成了UML /设计模式。
饮料是我的抽象组件类。 浓咖啡,houseblend,darkroast是我的具体主题类。
我也有一个调味品装饰类牛奶,摩卡,大豆,鞭子。 会是我的观察员? 因为他们会对数据更改感兴趣吗?
现在,浓咖啡,houseblend等会成为我的主题,调味品是我的观察者吗? 我的理论是,成本是一个变化,调味品需要知道变化?
所以,主题= esspresso,houseblend,darkroast等。//他们持有成本()
观察者=牛奶,摩卡,大豆,鞭子? //他们持有成本()
会是具体的组件和牛奶,摩卡,大豆,鞭子? 将是装饰者!
因此,遵循良好的软件工程实践“设计到接口而不是实现”或“识别那些不是那些改变的东西”
我需要一个costbehavior界面吗?
如果你看看UML,你会看到我要去的地方,看看我是否正确实现了观察者+装饰者模式? 我认为装饰者是正确的。
因为,图片不是很可见,我会在这里详细说明这些类:
饮料课(注册观察员,删除观察员,通知观察员,说明)
这些课程是具体的饮料课程
espresso,houseblend,darkroast,decaf(成本,getdescription,setcost,costchanged)
接口观察员类(更新)//成本?
接口costbehavior类(成本)//因为这改变?
调料装饰类(getdescription)
链接到2接口和装饰器的具体类是:牛奶,摩卡,大豆,鞭子(成本,getdescription,更新)这些是我的装饰器/包装类。
谢谢..
有没有办法让这张照片变大?
我可以看到装饰器在这里发挥作用,但我不太确定在这里使用观察者。 它似乎被迫。
几件事情:
我的建议是再次阅读Head First Design Pattern书(我认为你从哪里得到这个例子:),非常相似的领域),并且更好地理解这两种模式以及何时使用它们。
下面是装饰者和观察者一起工作的例子。 饮料组合是装饰者的实现。 订购系统是观察者(订单将通知寻呼机,寻呼机将执行某些操作)。 这里的场景是一个StarBuck咖啡店,他们会给你一个寻呼机,这样你就可以在你的饮料正在处理的时候做一些事情,一旦饮料准备就绪,你就会收到寻呼机的通知。
将示例保存为drink.cs,您可以使用csc(C: Windows Microsoft.Net Framework v3 .... csc / target:exe /out:drink.exe drink.cs)轻松编译该文件并运行它或使用VS或任何:)。
using System;
using System.Collections.Generic;
public interface IBeverage
{
string GetDescription();
decimal GetCost();
}
public abstract class Beverage : IBeverage
{
protected string _name;
protected decimal _cost;
public Beverage(string name, decimal cost)
{
_name = name;
_cost = cost;
}
public virtual string GetDescription()
{
return _name;
}
public virtual decimal GetCost()
{
return _cost;
}
}
public class Macchiato : Beverage
{
public Macchiato() : base("Macchiato", 3.50m) {}
}
public abstract class BeverageDecorator : Beverage
{
IBeverage _baseBeverage;
public BeverageDecorator(IBeverage baseBeverage) : base("", 0m)
{
_baseBeverage = baseBeverage;
}
public override string GetDescription()
{
return _name + " " + _baseBeverage.GetDescription();
}
public override decimal GetCost()
{
return _cost + _baseBeverage.GetCost();
}
}
public class Caramel : BeverageDecorator
{
public Caramel(IBeverage baseBeverage) : base(baseBeverage)
{
_name = "Caramel";
_cost = 0.50m;
}
}
public class Venti : BeverageDecorator
{
public Venti(IBeverage baseBeverage) : base(baseBeverage)
{
_name = "Venti";
_cost = 1.00m;
}
}
public class Iced : BeverageDecorator
{
public Iced(IBeverage baseBeverage) : base(baseBeverage)
{
_name = "Iced";
_cost = 0.25m;
}
}
public class Order
{
IBeverage _beverage;
IPager _pager;
public Order(IBeverage beverage, IPager pager)
{
_beverage = beverage;
_pager = pager;
}
public IPager Pager
{
get { return _pager; }
}
public IBeverage Beverage
{
get { return _beverage; }
}
}
public class OrderProcessing
{
Queue<Order> orders = new Queue<Order>();
public void NewOrder(IBeverage beverage, IPager pager)
{
orders.Enqueue(new Order(beverage, pager));
}
public void ProcessOrder()
{
if (orders.Count > 0)
{
var order = orders.Dequeue();
order.Pager.Update(order);
}
}
}
public interface IPager
{
void Update(Order order);
}
public class VibratingPager : IPager
{
string _number;
public VibratingPager(string number)
{
_number = number;
}
public void Update(Order order)
{
Console.WriteLine("BUZZZ");
Console.WriteLine("Your {0} is ready. Please pay {1} at the cashier after picking it up.", order.Beverage.GetDescription(),order.Beverage.GetCost());
}
}
public class Program
{
public static void Main(string[] args)
{
var orders = new OrderProcessing();
var pager1 = new VibratingPager("1");
var pager2 = new VibratingPager("2");
orders.NewOrder(new Iced(new Venti(new Caramel(new Macchiato()))), pager1);
orders.NewOrder(new Venti(new Macchiato()), pager2);
orders.ProcessOrder();
orders.ProcessOrder();
}
}
我绝对不是一个设计模式专家,但我觉得在这里你要让它变得比需要的复杂。 另外,我不是UML专家,但它是否将每种咖啡类型都作为一个单独的课程? 我认为让饮料类别具有类型属性/属性会更有意义,然后向此注入一个“成本 - 细节”类别,这将允许这些饮料报告正确的价格。
不,它根本就不对。 对不起,但事实并非如此。 这张图表明,一切都是一种饮料,在某些情况下是多次的。 显然,这些白色三角形中的一些应该是钻石,其中大部分可能是黑色的。 你使用的唯一关系是继承,这显然不是你的意图。
我也对设计理念,时期有严重的问题,但我想这是另一个讨论。 对于刚开始使用设计的人而言,你所做的一切都不同寻常(每个人都开始严肃地对待每一件该死的东西),所以我不会为此感到难过。 至少你在考虑设计,这真是一件好事。
回复评论:
什么都没有,只要在需要的地方应用。 当它应用于不适用的地方时,它有点儿不合适。 这里根本就不需要。 此外,你会做错了。 奶油不是咖啡的装饰者(我想这就是你想要做的)咖啡与奶油可能......但这仍然是过度设计。
装饰者为它装饰的东西添加行为。 假设你有一个消息类和一个显示输出的打印函数:
struct message
{
virtual void print() = 0;
};
struct concrete_message : message
{
void print() { std::cout << my_message << std::endl; }
};
现在让我们说你想让其中的一些缩进。 你可以通过使用“装饰器”来实现,该装饰器的子类AND包含一条消息:
struct tabbed_message
{
tabbed_message(message * msg) : my_message(msg) {}
void print() { std::cout << "t; my_message->print(); }
};
看看如何改变任何具体信息的行为而不必更改原始信息?
你对咖啡/调味品的看法并不是这样。 调味品就是你放入咖啡的东西。 例如,一杯带奶油或不含奶油的咖啡在行为上没有区别。 如果你想收取加奶油的费用,那么你只需将它与咖啡杯联系起来,当你询问杯子的数量时,就可以运行一杯咖啡。
链接地址: http://www.djcxy.com/p/32003.html上一篇: Observer pattern used with decorator pattern
下一篇: Question about decorator pattern and the abstract decorator class?