具有相同方法的多个类 - 最佳模式

时间:2010-04-05 13:23:16

标签: c# function class design-patterns

我目前的项目中有几个课程,需要验证电子邮件/网站地址。这样做的方法都是一样的。

我想知道实现这个的最佳方法是什么,所以我不需要将这些方法复制到任何地方?

这些类本身并不一定相关,它们只有那些共同的验证方法。

9 个答案:

答案 0 :(得分:17)

添加界面和使用扩展方法怎么样?

public interface IFoo { }

public class A : IFoo {}
public class B : IFoo {}
public class C : IFoo {}

public static class FooUtils {
    public static void Bar(this IFoo foo) { /* impl */ }
}

那样:

  • 没有不必要的继承
  • 没有重复

答案 1 :(得分:7)

您可能希望将所有验证代码放入Validator类中,然后在需要验证的任何位置使用该类。访问验证应该通过单一方法,Validate(object Something)。我认为这被称为“组合”(就设计模式而言)。

稍后,您可以将Validator的子类更具体或进行不同类型的验证。

您还可以让所有需要验证的类扩展一个基类或抽象类,其中包含90%的验证。

答案 2 :(得分:5)

听起来你只需要一个带静态方法的静态类

public static class Utilities{
    public static bool validEmail(string email)
    {
        //Your code here
    }
}

答案 3 :(得分:2)

是的,重复这段代码会很难闻,你可以在静态方法中将这些方法提取到单个Helper类,或者你可以定义一个“Validator”接口类并使用这个接口,你可以链接不同的验证方法。责任模式。

答案 4 :(得分:1)

创建一个Utility类,并将这些方法定义为适当的类/接口的扩展方法。

答案 5 :(得分:1)

您真的需要仔细研究面向方面的编程方法(AoP)。 Enterprise Library 4.1有一个名为Unity Interception的AoP实现。

http://msdn.microsoft.com/en-us/library/dd140045.aspx

此框架允许您为电子邮件验证编写单个处理程序类。所以这需要验证代码进入处理程序类,而不再是类的一部分。接下来要做的是标记拦截类。

您可以通过各种方式拦截类,包括根据您的要求设置应该截获和处理的所需方法的属性。设置属性可能是拦截的最简单方法。

答案 6 :(得分:0)

创建验证逻辑类和接口,并将它们注入到代码中......所以将逻辑从验证中分离出来,以便可以重用它......

答案 7 :(得分:0)

创建Email作为单独的类 在您的班级中使用Email作为属性/参数/返回值,而不是String 创建EmailValidator以将字符串验证为电子邮件地址 创建传递有效电子邮件地址时返回电子邮件的EmailFactory,否则返回null。

(网站也一样)。

答案 8 :(得分:0)

我建议您创建一个IValidator接口,然后创建多个不同的验证器来处理不同的场景。这是一个例子:

public interface IValidator {
    bool CanValidateType(string type);
    bool Validate(string input);
}

CanValidateType()方法可能有点复杂,但我希望你能理解。它基本上确定验证器是否可以处理提供的输入。以下是几个实现:

public class UrlValidator : IValidator {
    bool CanValidateType(string type) {
        return type.ToLower() == "url";
    }

    bool Validate(string input) {
        /* Validate Url */
    }
}

public class EmailValidator : IValidator {
    bool CanValidateType(string type) {
        return type.ToLower() == "email";
    }

    bool Validate(string input) {
        /* Validate Email */
    }
}

现在,您将使用构造函数注入将依赖项注入您的类:

public class SomeSimpleClass {
    private IValidator validator;

    public SomeComplexClass(IValidator validator) {
        this.validator = validator;
    }

    public void DoSomething(string url) {
        if (validator.CanValidateType("url") && 
            validator.Validate(url))
            /* Do something */
    }
}

当你有一个可以使用多个验证器的类时,CanValidateType会派上用场。在这种情况下,您将列表或验证器数组传递给构造函数。

public class SomeComplexClass {
    private List<IValidator> validators;

    public SomeComplexClass (List<IValidator> validators) {
        this.validators = validators;
    }

    public bool ValidateUrl(string url) {
        foreach (IValidator validator in this.validators)
            if (validator.CanValidateType("url"))
                return validator.Validate(url);
        return false;
    }


    public bool ValidateEmail(string email) {
        foreach (IValidator validator in this.validators)
            if (validator.CanValidateType("email"))
                return validator.Validate(email);
        return false;
    }
}

然后,您必须以某种方式将所需的验证器实例传递给您的类。这通常是使用IoC容器(如Castle Windsor)或自己完成的。

IValidator emailValidator = new EmailValidator();
IValidator urlValidator = new UrlValidator();
SomeSimpleClass simple = new SomeSimpleClass(urlValidator);
SomeComplexClass complex = new SomeComplexClass(new List<IValidator> { emailValidator, urlValidator });

上面的代码让你自己很烦人,这就是IoC容器如此方便的原因。使用IoC容器,您可以执行以下操作:

SomeSimpleClass simple = container.Resolve<SomeSimpleClass>();
SomeComplexClass complex = container.Resolve<SomeComplexClass();

接口的所有映射都在app.config或web.config中完成。

这是关于依赖注入和Castle Windsor IoC容器的an awesome tutorial