У меня очень простое приложение, которое состоит из сайта переднего плана ASP.NET, а служба Windows WCF выполняет сложную внутреннюю логику.
У пользователя есть одна простая страница, где он выбирает некоторые параметры и нажимает кнопку «Отправить». Страница вызывает службу WCF и передает ей параметры. Служба создает экземпляр класса «Job», отправляя параметры конструктору, а затем вызывает метод «Run ()», который выполняет всю работу - вставляет запись «job» в базу данных с именем пользователя, временем запущен и т. д. Делает запрос стороннему поставщику, получает данные, помещает их в базу данных, выполняет другую бизнес-логику, а затем отмечает работу как выполненную.
Затем у пользователя появляется вторая простая страница, где он может теперь искать свою работу (поле со списком с возможностью поиска, отсортированное по дате, отображая несколько полей, связанных с этой работой), а затем отображать данные, соответствующие этой работе, на экране - ( большинство полей из таблицы заданий, например время начала, время завершения, состояние и т. д., отображаются в виде меток на панели) и фактические данные, которые мы получили от стороннего поставщика (отображаются в виде таблицы под панелью).
Теперь перейдем к моему вопросу - поэтому у меня есть класс Job, в котором есть все поля, упомянутые выше, а также его открытый метод Run () и конструкторы. Он имеет несколько простых закрытых функций и несколько закрытых членов, которые являются интерфейсами к таким классам, как IParser, IVendorConnection, IDataAccess - классы, которые выполняют всю фактическую работу, описанную выше ... реальный класс Job и метод Run () не делают много фактическая работа, в основном просто делегирует работу ее составным объектам (кроме всего прочего, обеспечивает хорошую тестируемость).
Теперь этот класс Job имеет 3 возможных использования / состояния. Его основное использование находится внутри Сервиса, для использования функции Run () для буквального запуска задания. У него также есть два других применения - выступать в качестве модели для панели, которую я описал выше, и выступать в качестве модели для поля со списком, которое я описал выше. Класс задания имеет 3 открытых конструктора, каждый из которых настраивает его на одно из 3 состояний. Во всех случаях каждое отдельное «государство» заботится только об определенных участниках, о которых другие 2 государства не заботятся - в некоторых случаях некоторые из членов используются во всех 3 государствах. «Состояние поля со списком» является самым простым - в этом случае я хочу только 3 поля только для чтения. В «состоянии панели» я забочусь о 6 полях только для чтения… в состоянии «работа» я в основном создаю эти значения полей по мере выполнения задания - и все они должны быть частными.
Я просто ищу более чистый способ сделать это. Если я создаю экземпляр класса Job в состоянии A, я знаю , что доступ к члену X не будет работать или вызов функции Y завершится неудачно. Однако это все еще компилируемый код.
Я уверен, что другие сталкивались с этой проблемой раньше. Я думал о том, чтобы иметь базовый класс Job, помеченный как MustInherit / abstract, а затем иметь 3 производных класса, по одному для каждого состояния. Поместите общие члены в базу и специфичные для состояния в производную, и просто используйте производные классы в моем коде, где это уместно. Это кажется достаточно простым для моих целей и решает мою проблему. Возможно, у меня также может быть какой-то JobFactory ... Я думаю, я просто ищу, как другие люди решили это, так как, может быть, я не думаю, что нестандартно ... У меня было много классов быть конечными автоматами в моем дни разработки игр для любителей - но это было по-другому, потому что экземпляры этих классов могли изменять состояния (например, у класса «Враг» могло быть изменено его состояние с «attack_mode» на «ожидание»). В моем случае нет изменений состояний - После создания Иов должен оставаться в своем состоянии и никогда не пытаться вести себя по-другому. Отслеживание состояния и создание исключений, если метод / элемент используется, когда он не находится в заданном состоянии, кажется хрупким и слишком трудоемким. Любые предложения, основанные на том, как вы решили эту проблему раньше? И что я пытаюсь сделать излишним? Если бы Иов начал получать все больше и больше разных состояний, я бы подумал, что нет, но, может быть, если бы он получил так много разных состояний, тогда мне все равно нужно подумать о том, чтобы разделить его на разные классы ... Просто ищу ваши 2 цента.