java—使用基于用户输入的装饰器设计原理创建类示例

rm5edbpk  于 2021-07-08  发布在  Java
关注(0)|答案(3)|浏览(195)

目前我有如下可执行代码:

Sandwich sandwich_wTuna_wDoubleCheese = new Cheese(new Cheese(new Tuna(new Bread())));

为了更好地理解,sandwich是一个抽象类,由bread和sandwichdecorator扩展。三明治装潢师自己又是抽象的,并通过奶酪,金枪鱼,西红柿,扩展,。。你说吧。
现在这个工作很好,但我有一些面包店,应该出售这些三明治,创造使用装饰设计原则。我该怎么做?
我想我可以这样做:

List<String> list=new ArrayList<String>();
list.add("Cheese");
list.add("Cheese");
list.add("Tuna");
Sandwich sandwich_wTuna_wDoubleCheese = bakery1.SellBreads(list);

当然,我可以通过在示例已经做了面包房功能的装饰,但我希望有其他的方式。
你有办法解决这个问题吗?谢谢你的帮助和建议。

eulz3vhy

eulz3vhy1#

这表明您选择的设计模式与您的问题不匹配。
首先找出要对对象执行的操作,然后选择符合这些要求的设计模式。
你介绍了由部分三明治和一个附加层组成的化合物的(不同的)抽象(并且给出了这些化合物的误导性名称,仅暗示附加层)。
但是对于排序,您需要层本身的抽象,而这在您的模型世界中是不存在的。
所以,我会忘记你的装饰图案,而是创造 Sandwich 作为一个具有层列表的类,通常(但不一定?)以 Bread 层,然后是其他层。然后,可以通过在构造函数中提供层列表,或者通过调用现有三明治上的add(layer)方法来完成构造。

pxyaymoc

pxyaymoc2#

这看起来像是工厂的工作:)
尝试以下操作:

public interface IIngredient{}
public abstract class BaseIngredient : IIngredient
{
    private readonly IIngredient _inside;
    protected BaseIngredient(IIngredient inside)
    {
        _inside = inside;
    }
}

public class Tuna : BaseIngredient
{
    public Tuna(IIngredient inside) : base(inside)
    {
    }
}
public class Cheese : BaseIngredient
{
    public Cheese(IIngredient inside) : base(inside)
    {
    }
}
public class Bread : BaseIngredient
{
    public Bread(IIngredient inside) : base(inside)
    {
    }
}

public class IngredientFactory
{
    private readonly Dictionary<string, Func<IIngredient, IIngredient>> _ctors;

    public IngredientFactory()
    {
        _ctors = new Dictionary<string, Func<IIngredient, IIngredient>>()
        {
            {"tuna", (i) => new Tuna(i)},
            {"cheese", (i) => new Cheese(i)},
            {"bread", (i) => new Bread(i)},
        };
    }

    public IIngredient Create(string name, IIngredient inside)
    {
        if(!_ctors.ContainsKey(name))
            throw new ArgumentOutOfRangeException(nameof(name), "invalid ingredient");
        return _ctors[name](inside);
    }
}

在这种情况下,成分类型是硬编码的,但切换到更动态的方法是相当容易的。一个选项是扫描程序集以查找实现 IIngredient 接口。
成分名称也可以遵循约定并与类的小写版本匹配。
那么你要做的就是这样:

List<String> list = new List<String>();
list.Add("Cheese");
list.Add("Cheese");
list.Add("Tuna");

IIngredient result = null;

var factory = new IngredientFactory();
foreach (var name in list)
{
    result = factory.Create(name, result);
}
r8xiu3jd

r8xiu3jd3#

你可以使用 switchString 对于 List 创造一个三明治装饰层。

sandwich = switch (choice) {
    case "Cheese" -> new Cheese(sandwich);
    case "Tuna" -> new Tuna(sandwich);
    default -> throw UnknownSandwichChoice(choice);
};

可以对中的每个元素执行此操作 List 使用递归或迭代。

相关问题