Это гарантирует (или квалифицировать) как фабричный образец? - PullRequest
0 голосов
/ 23 февраля 2012

У меня есть коллекция строк, которые необходимо проанализировать (используя шаблоны RegEx) в надежде найти определенные типы информации. «Типы» информации могут быть адресом электронной почты, IP-адресом, полным доменным именем или чем-то еще. Исходная строка может иметь одно значение (один адрес электронной почты), несколько значений одного типа (например, два IP-адреса), сочетание значений (адрес электронной почты и IP-адрес) или ничего.

Для представления найденного шаблона у меня есть один класс, который имеет свойства для типа (email, ip и т. Д.) И его значения. Какой бы метод ни выполнял синтаксический анализ, он должен возвращать список указанного класса, где число может быть равно нулю, единице или более.

Мой вопрос: имеет ли смысл этот тип сценария для шаблона Factory? Я не могу использовать конструктор, в котором строка передается в качестве параметра, поскольку конструктор возвращает один экземпляр класса.

Тогда я рассуждаю об абстрактном подходе Фабрики, но формирую свое чтение. Фабрики предназначены для возврата разных классов.

Затем я прочитал еще один вопрос StackOverflow, где кто-то утверждает, что статический метод Create () класса WebRequest является шаблоном Factory. Итак, я думаю, могу ли я сделать это, передав исходную строку?

Обновление: на основе этого ответа (http://stackoverflow.com/a/4828511/240372) следует использовать фабричный шаблон, когда у вас есть "различные реализации одного и того же интерфейса". Поэтому мои требования не соответствуют этим критериям. Итак ... Я немного растерялся лучший подход ...

Редактировать: Я думаю, что мой пример использования адреса электронной почты и IP-адреса может привести к путанице с людьми, считающими, что я имею дело только с "адресами". Это не относится к делу. Позвольте мне добавить псевдокод, чтобы проиллюстрировать это.

Class TypeClass
   Property Name As String
   Property Pattern As String
End Class

Class FoundValue
   Property TypeName As String
   Property Value As String
End Class

Dim possibleTypes as List(Of TypeClass)
possibleTypes.Add(New TypeClass() With {.Name = "Email", .Pattern = "some_regex_pattern" }
possibleTypes.Add(New TypeClass() With {.Name = "IPAddress", .Pattern = "some_regex_pattern" }
possibleTypes.Add(New TypeClass() With {.Name = "Date", .Pattern = "some_regex_pattern" }
possibleTypes.Add(New TypeClass() With {.Name = "Integer", .Pattern = "some_regex_pattern" }

Dim sourceStrings as List(Of String)
sourceStrings.Add("hello")
sourceStrings.Add("1.2.3.4")
sourceStrings.Add("someone@somewhere.com; who@what.com")
sourceStrings.Add("C:\Windows\notepad.exe 24 who@what.com")

For Each source in sourceStrings
    For Each type in possibleTypes
       ' compare type.pattern to source and return list of list of FoundTypes 
       '
       ' for example, the last source string would return:
       '  list containing
       '     New FoundValue() With { .TypeName = "Integer", .Value = "24" }
       '     New FoundValue() With { .TypeName = "Email", .Value = "who@what.com" }
       '
       '  whereas the second source would return
       '  list containing
       '     New FoundValue() With { .TypeName = "IPAddress", .Value = "1.2.3.4" }

Спасибо.

Ответы [ 2 ]

0 голосов
/ 23 февраля 2012

Я так не думаю -

Мне кажется, что вы хотите создать общий интерфейс для чтения различных типов «вещей» из вашего текста.Я бы создал конкретные классы для каждого отдельного типа вещей, реализуя интерфейс ниже.

public interface IThingReader
{
    IEnumerable<Thing> ReadThing(string content);
}

Этот подход позволяет вам инкапсулировать чтение / разбор / построение адреса определенного типа в одном месте.В вашем случае вы можете создать класс для размещения коллекции читателей и объединения результатов всех из них.Например:

public class CompositeReader
{
    IThingReader[] Readers;

    public CompositeReader(IThingReader[] readers)
    {
       Readers = readers;
    }

    public List<Thing> ParseText(string text)
    {
        List<Thing> allThings = new List<Thing>();

           foreach(IThingReader reader in Readers)
           {
               IEnumerable<Thing> things = reader.ReadThing(text);
               allThings.AddRange(things);
           }

        return allThings;
    }
}

Фабрика была бы более полезна, если бы вам пришлось определять, какой тип вещи был в строке, и возвращать соответствующий результат.Например:

public class EmailAddress : Thing
public class IpAddress : Thing
public class Number : Thing

public class ThingFactory
{
    public Thing GetThing(string text)
    {
        if (IsEmailAddress(text))
        {
            return new EmailAddress(text);
        }
        else if (IsIpAddress(text))
        {
            int[] ipAddressParts = SplitIpAddressParts(text);
            return new IpAddress(ipAddressParts);
        }
        else
        {
            throw new UnrecognisedThingException(text);
        }
    } 
}

Таким образом, в приведенном выше примере фабрика используется для определения, какую отдельную реализацию класса Thing (общий интерфейс) создать.

0 голосов
/ 23 февраля 2012

Я не вижу здесь никакой необходимости в фабричном шаблоне по той причине, которую вы даете: у вас нет «различных реализаций одного и того же интерфейса».

Возможно, ваш синтаксический анализатор имеет код в этом стиле

 List<Address> result = new empty list; 

 for each found address
      Address oneAddress = new Address
      result.put(oneAddress)

Таким образом, у вас есть две точки создания: где вы создаете список и где вы создаете адрес.В каждом случае вы знаете тип, который вы хотите создать, так как ваш дизайн в настоящее время стоит, у вас нет нужды в фабрике.

Если вместо этого у вас было

 Interface Address
 Class EmailAddress implements Address
 Class IpAddress implements Address

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

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