Шаблон проектирования для создания набора объектов данных - PullRequest
2 голосов
/ 08 октября 2010

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

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

        contentTypes.Add(new ContentType { ContentName = "2010 Call Report", FolderName = "2010 Reports", RenameFile = false });
        contentTypes.Add(new ContentType { ContentName = "2010 Email Report", FolderName = "2010 Reports", RenameFile = false });
        contentTypes.Add(new ContentType { ContentName = "Above Average Call Recording", FolderName = "Call Recordings", RenameFile = true, HasMultiple = true });
        contentTypes.Add(new ContentType { ContentName = "Below Average Call Recording", FolderName = "Call Recordings", RenameFile = true, HasMultiple = true });

Это действительно не правильно (всего 11 строк практически идентичного кода), но я не могу думать, что еще мне следует делать.

Класс ContentType содержит несколько свойств, которые можно увидеть выше, и один открытый метод с именем GetNewFilename. В настоящее время метод GetNewFilename очень прост и используется всеми типами контента. Однако теперь я хочу, чтобы у нескольких объектов ContentType были свои версии этого метода ...

Я рассмотрел следующие вещи:

1) Подкласс ContentType для создания класса для каждого типа контента

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

2) Func собственность на ContentType

Я подумал, что мог бы установить делегата на ContentType, чтобы иметь дело с функцией GetNewFilename, отличной от нее, но он все еще чувствовал себя грязно, генерируя их способом, описанным выше.

3) Фабричные классы

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

4) Файл конфигурации

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

5) Наличие всех разных методов getNewFileName в одном классе

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

Так кто-нибудь может предложить хороший способ сделать это?

Вот текущая подпись для моего ContentType класса (с отключенной логикой - спросите, считаете ли вы ее уместной).

public class ContentType
{
    public string ContentName { get; set; }
    public string FolderName { get; set; }
    public bool RenameFile { get; set; }
    public bool HasMultiple { get; set; }

    public string GetNewFilename(string originalFilename, int fileIndex)
    {...} // This method needs to do diffent things for different contenttypes
}

Если вы хотите получить более подробную информацию о том, как используется этот класс, спросите, и я могу вставить его, но я не хотел забивать класс в коде, который, я не думаю, был уместен.

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

P.S. Теперь я также понимаю, что один или два конструктора, которые устанавливают эти начальные значения и делают их доступными только для чтения, были бы подходящими изменениями, чтобы привести их в порядок, но все же не решить всех моих проблем.

Ответы [ 3 ]

2 голосов
/ 08 октября 2010

Пусть ваш класс ContentType является базовым классом, а метод GetNewFilename - виртуальным.Получите классы ContentType для каждого типа файла, который может нуждаться в специальной обработке в методе GetNewFilename, и переопределите виртуальную реализацию.Затем просто создайте экземпляры этих унаследованных классов по мере необходимости, когда типы файлов, требующие специальной обработки, найдены в поиске в каталоге, в противном случае просто создайте экземпляр класса ContentType.

public class ContentType
{
    public virtual string GetNewFilename(string originalFilename, int fileIndex)
    {
        // get file name here
    }
}

public sealed class SpecialContentType : ContentType
{
    // Inherrits all the properties of ContentType

    public override string GetNewFilename(string originalFilename, int fileIndex)
    {
        // get special file name here
    }
}
1 голос
/ 09 октября 2010

Для # 4 вы можете использовать контейнер IoC, такой как Unity или StructureBuilder. Затем укажите класс для второй части:

public interface INewFilenameService {
  string FileName {get;set;}
}

public class ContentType {
    private INewFilenameService newFilenameService;

    public ContentType(INewFilenameService service) {
        this.newFilenameService = service;
    }

    public string ContentName { get; set; }
    public string FolderName { get; set; }
    public bool RenameFile { get; set; }
    public bool HasMultiple { get; set; }

    public string GetNewFilename() {
      return service.Filename;
    }
}

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

1 голос
/ 08 октября 2010

Другим шаблоном может быть интерфейс или абстрактный класс.Да, у вас будет 11 классов, но это не обязательно плохо.Это будет держать ваши проблемы в чистоте, в то же время предлагая общую основу.

Если GetFileName работает одинаково в нескольких случаях, вы можете реализовать абстрактный класс с помощью виртуального GetFileName метода.Это ограничило бы количество нового кода, который вы должны написать, переопределяя только при необходимости:

public abstract class ContentType
    {
        public string ContentName { get; set; }
        public string FolderName { get; set; }
        public bool RenameFile { get; set; }
        public bool HasMultiple { get; set; }

        public virtual string GetFileName()
        { 
            //Base GetFileName implementation
            return "filename";
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...