这是否符合(或符合资格)工厂模式?

时间:2012-02-23 06:07:40

标签: design-patterns factory-pattern

我有一组需要解析的字符串(使用RegEx模式),希望找到某些类型的信息。信息的“类型”可以是电子邮件地址或IP地址或FQDN等等。源字符串可以具有单个值(一个电子邮件地址),相同类型的多个值(例如,两个IP地址),值的混合(电子邮件地址和IP地址),或者什么都不是。

为了表示找到的模式,我有一个类,它具有类型(电子邮件,IP等)及其值的属性。无论采用何种方法,解析都应该返回所述类的列表,其中计数可以是零,一个或多个。

我的问题是这种情况对工厂模式有意义吗?因为构造函数返回单个类实例,所以我不能使用将字符串作为参数传入的构造函数。

然后我讨论了抽象的工厂方法,但形成了我的阅读工厂旨在返回不同的类。

然后我读了另一个StackOverflow问题,其中有人声称WebRequest类的静态Create()方法是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 :(得分:0)

我认为这里不需要工厂模式,因为你给出的原因是:你没有“同一界面的不同实现”。

您的解析器可能包含此样式的代码

 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对象。

答案 1 :(得分:0)

我不这么认为 -

听起来我觉得你想要一个通用界面来阅读你文本中不同类型的“东西”。我将为实现以下接口的每种不同的类型创建具体的类。

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类(通用接口)的哪个不同实现。