Какой шаблон дизайна использовать? - PullRequest
2 голосов
/ 14 апреля 2011

Меня спросили в недавнем интервью:

Сэндвич должен иметь ровно два ломтика хлеба (по одному на каждом конце) и любое положительное количество сыров между ними.

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

Какой шаблон проектирования вы могли бы использовать, чтобы каждый экземпляр сэндвича был действительным сэндвичем?

Ответы [ 3 ]

9 голосов
/ 14 апреля 2011

Вы можете использовать шаблон Builder: Используется для очень сложного многоэтапного конструирования объектов, где число аргументов конструктора или метода будет смехотворно большим.

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

Неполный SandwichBuilders может выдать какой-то IncompleteSandwichException, если он не завершен правильно при вызове .getSandwich().

Примечание: с правильно названными методами построения, вы ненужно сделать что-нибудь в определенном порядке.

Или вы можете использовать шаблон FactoryMethod: Когда число шагов вписывается в один вызов метода с разумным количеством аргументов,и объект должен быть полностью завершен.

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

Или используйте Constructor: , который является специализированным случаем FactoryMethod pattern

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

перегруженный конструктор для добавления сыра:

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

Существует множество способов сделать это в зависимости от того, насколько строгой должна быть конструкция.Например, вы можете сделать реализацию Sandwich inner class объекта Factory/Builder и сделать его конструктором private, чтобы его нельзя было создать неправильно.

6 голосов
/ 14 апреля 2011

Я думаю, что шаблон Builder может быть хорошим выбором здесь.

0 голосов
/ 14 апреля 2011

Я реализовал решение, используя

Шаблон шаблона.

Хотя решение находится в 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 };
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...