gpt4 book ai didi

design-patterns - 观察者模式与装饰者模式一起使用

转载 作者:行者123 更新时间:2023-12-02 02:28:46 25 4
gpt4 key购买 nike

我想制作一个程序来执行饮料订单输入系统。 (我可能会做描述,费用)

我想使用装饰者模式和观察者模式。我画了一张UML图,保存为图片方便查看。该站点不允许我以 word 文档形式上传,因此我必须上传图片 - 我希望它易于查看....

在继续编码部分之前,我需要知道我是否正确地执行了 UML/设计模式。

饮料是我的抽象组件类。Espresso、houseblend、darkroast 是我的具体主题类(class)..

我还有一个调味品装饰类牛奶,摩卡咖啡,大 bean ,鞭子。会是我的观察员吗?因为他们会对成本的数据更改感兴趣?

现在,espresso、houseblend 等会成为我的主题,而调味品会成为我的观察者吗?我的理论是,Cost 是一种变化,调味品需要知道这种变化吗?

所以,subject = esspresso,houseblend,darkroast,etc..//他们持有 cost()

Observer = 牛奶、摩卡咖啡、大 bean 、鞭子?//他们持有 cost()

将是具体的组件和牛奶,摩卡咖啡,大 bean ,鞭子?将是装饰者!

因此,遵循良好的软件工程实践“针对接口(interface)而不是实现进行设计”或“识别那些没有变化的事物”

我需要一个 costbehavior 接口(interface)吗?

如果你看一下 UML,你就会明白我要用它做什么,看看我是否正确地实现了观察者 + 装饰器模式?我认为装饰器是正确的。


由于图片不太清晰,我将在此处详细介绍这些类:

饮料类(注册观察者、移除观察者、通知观察者、描述)

这些类是具体的饮料类

espresso、houseblend、darkroast、decaf(cost,getdescription,setcost,costchanged)

接口(interface)观察者类(更新)//成本?

interface costbehavior class(cost)//因为这个改变了?

调味品装饰器类(getdescription)

链接到 2 个接口(interface)和装饰器的具体类是:牛奶、摩卡咖啡、大 bean 、鞭子(成本、获取描述、更新)这些是我的装饰器/包装器类。

谢谢你..

alt text

有没有办法让这张图片变大?

最佳答案

我可以看到装饰器在这里发挥作用,但我不太确定在这里使用观察者。这似乎是被迫的。

几件事:

  1. CondimentDecorator 需要用一种饮料来装饰。它不会显示在您的 UML 中。将其视为某种东西的包装器,类似于适配器模式。 wrapper 需要包裹一些东西。你显然没有表现出来。
  2. 在你的成本行为接口(interface)上,为什么具体的装饰器会实现它,而具体的饮料却没有,而且饮料也有成本?我只想让饮料接口(interface)继承自成本行为接口(interface)并完成它。
  3. #2 也适用于 getDescription 方法...创建一个 IDescribable?或其他东西并让饮料实现它。 Decorator会通过继承来获取。
  4. 你需要说服我为什么调味品需要知道价格何时变化?目前,这对我来说似乎有点被迫。我不明白这里如何需要观察者(逻辑上/设计方面)。在我看来,除了你必须拥有它之外,你没有任何理由想要将观察者模式强加到这个设计中。对于刚刚了解设计模式的人来说,这是一个经典的模式狂热的东西。不想冒犯,只是陈述事实。我曾经也是这样的人:)。

我的建议是再次阅读 Head First Design Pattern 一书(我认为您可以从中获得这些示例 :),非常相似的领域)并更好地理解这两种模式以及何时使用它们。

下面是一个装饰者和观察者一起工作的例子。饮料组合是装饰器的一个实现。订购系统是一个观察者(订单将通知寻呼机,寻呼机将执行某些操作)。这里的场景是一家星巴克咖啡店,他们会给你一个寻呼机,这样你就可以在处理饮料的同时四处走动,一旦饮料准备好,寻呼机就会通知你。

将示例保存为 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();
}
}

关于design-patterns - 观察者模式与装饰者模式一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4697170/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com