使用哪种设计模式?

发布于 2024-11-01 07:41:38 字数 309 浏览 0 评论 0原文

最近的一次采访中有人问我:

三明治应该正好有两片面包 (两端各一个),以及中间任意正数的奶酪。

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());

您可以使用什么设计模式来确保实例化的每个三明治都是有效的三明治?

I was asked in a recent interview:

A Sandwich should have exactly two slices of bread
(one on each end), and any positive number of Cheeses in between.

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());

What design pattern could you use to ensure that every Sandwich instantiated is a valid sandwich?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如梦初醒的夏天 2024-11-08 07:41:38

您可以使用Builder模式:用于非常复杂的多步骤对象构造,其中构造函数或方法参数的数量会高得离谱。

SandwichBuilder sb = new SandwichBuilder();
sb.addFirstBread(new BreadSlice());
sb.addCheese(new Cheese());
...
sb.addLastBread(new BreadSlice());
Sandwich s = sb.getSandwich();

不完整SandwichBuilders<如果在调用 .getSandwich() 时未正确完成,/code> 可能会抛出某种 IncompleteSandwichException

注意: 使用正确命名的构造方法,您不需要按特定顺序执行任何操作。

或者您可以使用 FactoryMethod 模式: 当步骤数适合具有合理数量参数的单个方法调用时,并且应保证对象处于完整状态。

BreadSlice bs1 = new BreadSlice();
BreadSlice bs2 = new BreadSlice();
List<Cheese> cheeses = new ArrayList<Cheese>();
...
Sandwich s = SandwichBuilder.buildSandwich(bs1, cheeses, bs2);

或者使用构造函数这是一个特例FactoryMethod 模式

Sandwich s = new Sandwich(bs1, cheeses, bs2);

重载构造函数以允许添加奶酪:

Sandwich s = new Sandwich(bs1, bs2);
s.addCheese(new CheeseSlice());
...

有很多方法可以做到这一点,具体取决于您希望构造的严格程度。
例如,您可以将 Sandwich 实现设为 Factory/Builder 对象的内部类,并将其构造函数设为私有 所以它不能被错误地实例化。

You could use a Builder pattern: Used for very complicated multi-step object construction, where the number of constructor or method arguments would be ridiculously high.

SandwichBuilder sb = new SandwichBuilder();
sb.addFirstBread(new BreadSlice());
sb.addCheese(new Cheese());
...
sb.addLastBread(new BreadSlice());
Sandwich s = sb.getSandwich();

incomplete SandwichBuilders could throw some kind of IncompleteSandwichException if not completed correctly when .getSandwich() is called.

Note: with properly named construction methods, you don't need to do anything in a specific order.

Or you could use a FactoryMethod pattern: When the number of steps would fit into a single method call with a reasonable number of arguments, and the object should be guaranteed to be a complete state.

BreadSlice bs1 = new BreadSlice();
BreadSlice bs2 = new BreadSlice();
List<Cheese> cheeses = new ArrayList<Cheese>();
...
Sandwich s = SandwichBuilder.buildSandwich(bs1, cheeses, bs2);

Or use the Constructor: which is a specialized case of FactoryMethod pattern

Sandwich s = new Sandwich(bs1, cheeses, bs2);

overloaded constructor to allow for cheese addition:

Sandwich s = new Sandwich(bs1, bs2);
s.addCheese(new CheeseSlice());
...

There are lots of ways to do this depending on how strict you want the construction to be.
For example, you can make the Sandwich implementation an inner class of the Factory/Builder object and make its constructor private so it can't be instantiated in-correctly.

懒的傷心 2024-11-08 07:41:38

我认为 Builder 模式在这里可能是一个不错的选择。

I think the Builder pattern could be a good choice here.

楠木可依 2024-11-08 07:41:38

我已经使用以下方法实现了该解决方案

模板模式。

虽然解决方案是用 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 };
    }
}

I have implemented the solution using

Template pattern.

Though the solution is in C# it can easily be modified to run in Java environment.


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 };
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文