如何解决使用哪种设计模式?
| 在最近的一次采访中有人问我: 三明治应该正好有两片面包 (两端各一个),以及介于两者之间的任意数量的奶酪。Sandwich s = new Sandwich();
s.add(new BreadSlice());
s.add(new CheddarCheese());
s.add(new SwissCheese());
s.add(new BreadSlice());
System.println(\"My sandwich: \"+ s.toString());
您可以使用哪种设计模式来确保实例化的每个三明治都是有效的三明治?
解决方法
您可以使用
Builder
模式:用于非常复杂的多步对象构造,其中构造函数或方法参数的数量非常高。
SandwichBuilder sb = new SandwichBuilder();
sb.addFirstBread(new BreadSlice());
sb.addCheese(new Cheese());
...
sb.addLastBread(new BreadSlice());
Sandwich s = sb.getSandwich();
如果调用completed5ѭ时未正确完成,SandwichBuilders
可能会抛出某种IncompleteSandwichException
。
注意:使用正确命名的构造方法,您无需按特定顺序执行任何操作。
或者,您可以使用FactoryMethod
模式:当步骤的数量适合具有合理数量的参数的单个方法调用时,并且应确保对象为完整状态。
BreadSlice bs1 = new BreadSlice();
BreadSlice bs2 = new BreadSlice();
List<Cheese> cheeses = new ArrayList<Cheese>();
...
Sandwich s = SandwichBuilder.buildSandwich(bs1,cheeses,bs2);
或使用Constructor
:这是FactoryMethod
模式的特殊情况
Sandwich s = new Sandwich(bs1,bs2);
重载的构造函数以允许添加奶酪:
Sandwich s = new Sandwich(bs1,bs2);
s.addCheese(new CheeseSlice());
...
有多种方法可以执行此操作,具体取决于您希望结构的严格程度。
例如,您可以使Sandwich
实现成为Factory/Builder
对象的inner class
,并将其构造函数private
使其无法正确地实例化。
,我认为在这里Builder模式可能是一个不错的选择。
,我已经使用实现了解决方案
模板模式。
尽管该解决方案是用C#编写的,但可以轻松修改以在Java环境中运行。
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DeliverSandwitch(new MinimumCheese());
DeliverSandwitch(new MixCheese());
DeliverSandwitch(new DoubleSwissCheese());
Console.ReadLine();
}
private static void DeliverSandwitch(BaseSandwitch customSandwitch)
{
Console.WriteLine(customSandwitch.Name);
Console.WriteLine(\"-----------------------------------\");
foreach (string layer in customSandwitch.Layers)
Console.WriteLine(layer);
Console.WriteLine();
Console.WriteLine();
}
public abstract class BaseSandwitch
{
List<string> layers = new List<string>();
protected virtual CheeseType DefaultCheese { get { return CheeseType.PlainCheese; } }
public abstract string Name { get; }
public BaseSandwitch()
{
SandwitchTemplate();
}
private void SandwitchTemplate()
{
AddBaseBread();
AddCheese(DefaultCheese);
AddAdditionalCheese();
AddTopBread();
}
private void AddTopBread()
{
layers.Add(\"Top bread\");
}
public abstract void AddAdditionalCheese();
private void AddBaseBread()
{
layers.Add(\"Base bread\");
}
protected void AddCheese(CheeseType cheeseType)
{
layers.Add(cheeseType.ToString());
}
public IEnumerable<string> Layers { get { return layers; } }
}
class MinimumCheese : BaseSandwitch
{
public override string Name { get { return \"Minimum cheese Sandwitch\"; }}
public override void AddAdditionalCheese()
{
// I come with no additional cheese
}
// I do not like PlainCheese. Replacing with CheddarCheese
protected override CheeseType DefaultCheese
{
get { return CheeseType.CheddarCheese; }
}
}
/// <summary>
/// I am ok with default cheese and would like to have other cheese as well
/// </summary>
class MixCheese : BaseSandwitch
{
public override string Name { get { return \"Mix cheese Sandwitch\"; } }
public override void AddAdditionalCheese()
{
AddCheese(CheeseType.CheddarCheese);
AddCheese(CheeseType.SwissCheese);
}
}
class DoubleSwissCheese : BaseSandwitch
{
public override string Name { get { return \"Double Swiss Cheese Sandwitch\"; } }
public override void AddAdditionalCheese()
{
// Adding another layer of swiss cheese
AddCheese(CheeseType.SwissCheese);
}
// I like swiss cheese by default instead of PlainCheese
protected override CheeseType DefaultCheese
{
get { return CheeseType.SwissCheese; }
}
}
public enum CheeseType { PlainCheese,SwissCheese,CheddarCheese };
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。