我想做一个程序,为饮料做订单输入系统。(我可能会做描述,费用)
我想使用Decorator模式和观察者模式。为了便于查看,我制作了UML绘图,并将其保存为图片。这个网站不会让我上传成文字文档,所以我必须上传一张图片-我希望它容易查看.
在进入编码部分之前,我需要知道我是否正确地执行了UML /设计模式。
饮料是我的抽象成分课。浓咖啡,混合咖啡,黑烤是我的具体课程。
我也有调味品装饰类牛奶,摩卡,大豆,鞭子。会是我的观察者吗?因为他们会对数据更改成本感兴趣?
现在,我的主题是浓咖啡、家庭混和等,调味品是我的观察者吗?我的理论是,成本是一种变化,调味品需要知道变化吗?
所以,主题= esspresso,房屋混合,暗烤等等。//他们持有成本()
观察者=牛奶,摩卡,大豆,鞭子? //他们持有成本()
会是混凝土成分和牛奶,摩卡,大豆,鞭子?就是那个装潢师!
因此,遵循良好的软件工程实践--“设计到接口而不是实现”或“识别出那些不能改变的东西”。
我需要一个成本行为界面吗?
如果您查看UML,您将看到我在做这件事,看看我是否正确地实现了观察者+装饰器模式?我认为装潢师是对的。
由于图片不是很直观,所以我将在这里详细介绍这些类:
饮料类(注册观察者,删除观察者,通知观察者,描述)
这些类是混凝土饮料类。
浓缩咖啡,混合咖啡,深色烤咖啡,无咖啡因咖啡(价格,价格,价格)
接口观察者类(更新) //成本?
接口成本行为类(成本) //因为这改变了?
调味品装饰类( getdescription)
链接到两个接口的具体类是:牛奶、摩卡、大豆、鞭子(成本、getdescription、update) --这些是我的装饰器/包装类。
谢谢。。

有办法把这幅画画得更大吗?
发布于 2011-01-15 02:47:01
我可以看到装饰师在这里发挥作用,但我不太确定在这里使用观察员。这似乎是被迫的。
有几件事:
我的建议是重读“第一设计模式”(我认为这是从哪里得到的示例:),非常相似的领域),并更好地理解这两种模式以及何时使用它们。
下面是装饰师和观察者一起工作的一个例子。饮料组合是装饰师的一种实现。订购系统是一个观察者(订单会通知寻呼机,寻呼机会做一些事情)。这里的场景是一个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();
}
}发布于 2011-01-15 00:07:49
我绝对不是一个设计模式专家,但我在这里觉得你正在使这比它所需要的更复杂。另外,我不是UML专家,但是您是否将每种咖啡类型作为单独的类来使用呢?我认为,如果有一个具有类型属性/属性的饮料类,然后在其中注入一个“成本-细节”类,将使这些饮料能够报告正确的价格,这将是更有意义的。
发布于 2011-01-15 01:03:42
不是的。这根本不对。对不起,但事实并非如此。那张画上写着,每样东西都是饮料,在某些情况下,很多次都是这样。很明显,其中一些白色三角形应该是钻石,其中大部分可能是黑色的。您所使用的唯一关系是继承,这显然不是您的意图。
我也有严重的问题的设计理念,期间,但我想这是另一个讨论。对于刚开始于设计的人来说,你所做的一切都是不寻常的(每个人一开始都会把每件该死的事情都搞得太过分),所以我不会为此感到难过。至少你在考虑设计,这是一件非常好的事情。
对评论的答复:
什么都没有,在需要的地方应用。当它被应用在不适用的地方的时候。这里根本不需要它。而且,你做错了。奶油不是咖啡的装潢师(我想这就是你想要做的),加奶油的咖啡可能是be...but,它仍然是过度设计的。
装潢师在装潢的东西上增加行为。假设您有一个消息类和一个显示输出的打印函数:
struct message
{
virtual void print() = 0;
};
struct concrete_message : message
{
void print() { std::cout << my_message << std::endl; }
};现在让我们说你想让他们中的一些人缩进。您可以通过使用“装饰器”来做到这一点,该子类包含消息:
struct tabbed_message
{
tabbed_message(message * msg) : my_message(msg) {}
void print() { std::cout << "\t; my_message->print(); }
};看看这如何改变任何具体消息的行为而不必更改原始消息?
你的咖啡/调味品不是这样的。调味品就是你放进咖啡里的东西。一杯咖啡和不加奶油的咖啡在行为上没有区别(例如)。如果你想对添加的奶油收取费用,那么你只需将它与一杯咖啡联系起来,当你问这个杯子多少钱时,你就算出一个总数。
https://stackoverflow.com/questions/4697170
复制相似问题