Как бы вы закодировали стиральную машину?

Представьте, что у меня есть класс, который представляет собой простую стиральную машину. Он может выполнять следующие операции в следующем порядке: включить → промывка → центрифуга → выключить. Я вижу две основные альтернативы:

  • У меня может быть класс WashingMachine с методами turnOn(), wash (int minutes), центрифуга (int revs), turnOff(). Проблема заключается в том, что интерфейс говорит ничего о правильном порядке операций. Я могу в лучшем случае выбросить InvalidOprationException, если клиент пытается центрифугировать до включения машины. Я также могу использовать класс программ Separete, который будет передавать обороты центрифуги и минуты стирки в стиральную машину и упростит эти методы.

  • Я могу позволить самому классу заботиться о правильных переходах и иметь единственный метод nextOperation(). Проблема с этим, с другой стороны, заключается в том, что семантика плоха. Клиент не будет знать, что произойдет, когда он называет nextOperation(). Представьте, что вы выполняете клик на кнопке центрифуги, чтобы он вызывал nextOperation(). Пользователь нажимает кнопку центрифуги после включения и запуска машины! машина начинает стирать. Мне, вероятно, понадобится несколько свойств в моем классе для параметризации операций или, возможно, отдельный класс программы с полями washLength и centrifugeRevs, но это не проблема.

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

Ответ 1

Я думаю, что turnOn(), wash(), centerfuge() и т.д. должны быть частными/защищенными методами. Открытый интерфейс должен быть doTheWash (режим WashMode). Сама стиральная машина знает режимы, которые она поддерживает, и как заставить их работать, пользователь стиральной машины не должен вмешиваться в порядок или продолжительность операций. Разумно ожидать, что автор класса стиральной машины вызовет частные методы в разумном порядке.

Ответ 2

У меня будет класс "высокий уровень" State Machine, который контролирует ввод/выполнение/выход каждого состояния (где состояния могут быть такими, как "заполнение", "стирка", "полоскание", "опорожнение", "спина сухая" и т.д.)

Составьте диаграмму перехода состояния всех состояний, в которых вы нуждаетесь, в том числе (для каждого состояния)

  • какие требования существуют до того, как вы войдете в состояние (условия входа)
  • что должно произойти при вводе состояния (действия входа)
  • что происходит во время состояния (сама задача)
  • какие существуют требования перед тем, как вы сможете покинуть состояние (условия выхода)
  • что происходит, когда вы выходите из состояния (действия выхода)

Вы можете или не нуждаться в условиях входа/выхода (например, вы можете принудительно принудительно выполнить условия с действием входа/выхода в некоторых случаях). Однако из соображений безопасности некоторые условия могут быть хорошими (например, выходить из состояния ожидания или входить в "опасное" состояние, такое как сухая спина)

Вы также создаете Transitions, которые определяют связи между состояниями. Переход имеет

  • a 'from' state
  • a 'to' state
  • условия перехода (возможен ли переход?
  • действия перехода (что должно произойти при переходе)

Опять же, вам может не понадобиться все это, и многие переходы будут иметь только указанные "от" и "от" состояния.

В обоих случаях старайтесь держать все State и Transition настолько простыми, насколько это необходимо (попробуйте поместить условия/действия там, где они имеют наибольший смысл, очевидно, что потенциальное их удвоение определенные в State и a Transition из-за общей конструкции)

В этот момент должно быть довольно очевидно, что вы можете создать довольно общий State класс, который включает абстрактные/перегружаемые функции для всех этих вещей, а также для класса Transition. Класс State Machine может вызывать каждую из этих функций-членов по мере необходимости на основе запрошенных им переходов.

Если вы сделаете его особенно общим, то States и Transitions могут быть зарегистрированы с State Machine во время построения, или вы можете просто скопировать State Machine, чтобы содержать их все.

Затем вы можете запросить переходы либо изнутри состояний (то есть конкретное состояние может узнать, когда оно закончилось, и узнать, какое состояние перейти к следующему), либо вы можете иметь внешний класс, который управляет переходами состояния (каждое состояние то очень просто, чисто заботясь о своих действиях, а внешний класс решает порядок и время переходов).

В моем опыте с этими вещами, хорошая идея отделить логику высокого уровня преднамеренного порядка/времени каждого действия и логику низкого уровня реакции на какое-то аппаратное событие (например, переход из состояния "заполнения", когда уровень воды достигнут).

Это действительно общий дизайн, хотя вы можете достичь точно такой же функциональности кучей разных способов - редко есть один правильный способ делать что-то...

Ответ 3

Большинство западных стиральных машин используют таймер для перехода от цикла к циклу. Этот таймер можно рассматривать как машину состояний. Тем не менее, важно понимать, что машина для обезжиривания работает сама, а не пользователь. Пользователь устанавливает начальный режим, а затем он продолжает свою деятельность.

Таким образом, внутренне вы можете использовать функции Wash, Rinse, Spin private, фактическим интерфейсом будет SetCycle() и Start() и Stop(). У вас также могут быть дополнительные свойства, такие как уровень воды, скорость перемешивания, температура воды и т.д.

Запуск вызывает время для продвижения, которое через некоторое время переходит в следующее состояние, пока, наконец, оно не будет завершено.

Ответ 4

Каждая стиральная машина имеет контроллер и программу. Для старых и простых машин программа и контроллер интегрированы в довольно сложную ручку, современные и более дорогие машины имеют компьютер.

В любом случае машина имеет дополнительные подсистемы, а контроллер уведомляет подсистемы для выполнения некоторых действий, таких как блокировка двери, нагревание воды до 40 ° C или вращение барабана.

Сам контроллер знает последовательность, которая довольно линейна и основана на таймере для старых машин или сложна для современных систем, которые изменяют последовательность, основанную на данных датчика. Но в любом случае он выполняет ряд команд, которые могут уведомлять датчики и участников.

Если вы посмотрите на стиральную систему с этой точки зрения, вы можете использовать шаблон Command внутри контроллера для моделирования программы стирки и Observer шаблон для уведомления подсистем (например: дверной выключатель прослушивает контроллер для сигнала для блокировки двери).

Ответ 5

Первое - это именно то, что я сделал бы. wash и centrifuge будут проверять флаг, который отслеживает, включен ли компьютер и выдает исключение, если это не так, но в противном случае нет обязательного порядка операций; вы можете называть centrifuge до wash, если вы действительно почувствовали потребность

Ответ 6

Erm, немного странно, но здесь идет;

Я бы посмотрел даже на делегатов. Таким образом, для конкретного типа цикла стирки, взрыва, света, шудди, экономичности и т.д. Я бы сказал, что интерфейс для каждого.

Затем, с использованием дженериков, я бы создал подходящий тип стирки, который я хочу.

Затем тип стирки должен иметь событие стирки, которое делегирует для выполнения циклов.

Ответ 7

Стиральная машина должна знать, как правильно запускать нагрузку. Возможно, перед стиркой нагрузки должны быть установлены определенные элементы конфигурации (со значениями по умолчанию, если они не установлены), например, какой тип нагрузки (огни против темных) или размер (маленький, средний, большой). Пользователь (другой класс) должен знать, как правильно настроить загрузку, но для стирки нагрузки стиральная машина должна только выставлять один метод, например washLoad. Внутри он справлялся бы с тем, что нужно было бы вызывать, когда мыть белье.

Кроме того, вы все равно можете публиковать публичные функции для включения и выключения шайбы, а затем, если washLoad были вызваны, когда шайба выключена, было бы целесообразно создать исключение. Кроме того, в этом случае я бы, вероятно, установил параметры для шайбы, установленной с помощью одного метода setLoadOptions, который возьмет другой класс, будет что-то вроде LoadOptions и определит любые характеристики, которые вы хотите настроить. Я хотел бы, чтобы этот метод также выдавал исключение, если шайба не была включена.

Ответ 8

На моей стиральной машине у вас есть доступ к двум ручкам. Я немного смущен относительно того, какие ограничения существуют в вашем случае.

  • Размер загрузки (малый, средний, большой)
  • Ручка цикла (пермский пресс, вязаные и деликатные, обычные)
    • Каждый цикл содержит разные "фазы", ​​при которых его можно активировать с помощью

Когда вы активируете цикл (поворачивая ручку), машина начнет работать, если вы перевернете его в середине или в начале цикла.

Вот действительно, действительно базовый пример того, как я буду переводить это в класс:

class WashingMachine
{
    public void Activate(Cycle c, LoadSize s);
    ...
}

Ответ 9

В последнее время я шел функциональный и использовал неизменяемые объекты с Мартин Фаулер /JQuery, цепляющий беглый стиль.

  • Я использую систему типов как можно больше, поскольку она делает рефакторинг.
  • С помощью моего метода компилятор заставит вас сделать это правильно.
  • Поскольку объекты несколько неизменны, проще доказать, что математически эта машина состояний детерминирована.

код:

public class Washer {
    public void exampleRun() {
        new On()
            .wash(30)
            .spin(100)
            .turnOff();
    }
    public abstract static class State {}
    public static class On extends State {
        public Wash wash(int minutes) {
            return new Wash(minutes);
        }
    }
    public static class Wash extends State {
        private int minutes;
        public Wash(int minutes) {
            super();
            this.minutes = minutes;
        }

        public Spin spin(int revs) {
            return new Spin(revs);
        }

    }
    public static class Spin extends State {
        private int revs;
        public Spin(int revs) {
            super();
            this.revs = revs;
        }
        public Off turnOff() {
            return new Off();
        }
    }
    public static class Off extends State{}
}

Ответ 10

Вариант A похож на ручную стиральную машину, а опция B похожа на автоматическую шайбу. Оба варианта полезны для пользователей таргетинга:

Пользователь опции A может вручную программировать весь процесс (например, удваивать кружок стирки или обучать маленького, что, если вы выключаете машину, когда она находится в центре центрифугирования).

Пользователь варианта B может наслаждаться простотой и писать фиктивные сериалы - научите себя стирать за 21 секунду: -)