2016-02-05 31 views
1

我试图用仿制药实现工厂模式。我不知道如果我采取正确带仿制药的工厂模式

interface DocumentValidator<T> { 
    Boolean validate(Document document, T object) 

} 

class ShipmentDocumentValidator implements DocumentValidator<Shipment>{ 
     @Override 
     Boolean validate(Document document, Shipment object) { 
      return true 
     } 
} 

class DocumentValidatorFactory { 
    static DocumentValidator forClass(Class clazz) { 
     if (clazz.simpleName.contains('Shipment')) { 
      return new ShipmentDocumentValidator(); 
     } 
    } 
} 

调用代码:

DocumentValidator validator = DocumentValidatorFactory.forClass(Shipment.class) 

我不认为我应该依赖于类的名字,但我怎么能以其它方式实现

回答

0

如果你的参数分别是a String,那么这种比较是可行的,但在这种情况下,您可以简单地比较该类别:

if (clazz == Shipment) { 
    return new ShipmentDocumentValidator(); 
} 

但你也可以使用地图类为重点,并验证为值:

class Shipment {} 
class Invoice {} 
class Document {} 

interface DocumentValidator<T> { 
    Boolean validate(Document document, T object) 
} 

class ShipmentDocumentValidator implements DocumentValidator<Shipment>{ 
    Boolean validate(Document document, Shipment object) { 
     true 
    } 
} 

class InvoiceDocumentValidator implements DocumentValidator<Invoice>{ 
    Boolean validate(Document document, Invoice object) { 
     true 
    } 
} 

class DocumentValidatorFactory { 
    static DocumentValidator forClass(Class clazz) { 
     [ 
      (Shipment) : ShipmentDocumentValidator, 
      (Invoice) : InvoiceDocumentValidator 
     ][clazz].newInstance() 
    } 
} 


assert DocumentValidatorFactory.forClass(Shipment) instanceof ShipmentDocumentValidator 
assert DocumentValidatorFactory.forClass(Invoice) instanceof InvoiceDocumentValidator 
+0

是的,坏主意检查一个字符串。没有编译时验证,所以如果您不小心键入“Shiqment”而不是“Shipment”,则会得到不正确的结果,并且不会显示警告。我曾经使用一个系统,原始程序员经常围绕硬编码的字符串进行处理,并且发现了代码不正确的情况,因为他们在“运费”,“运费”而不是“运费” capitalizatoin - 如果你错过了差异,他们也是如此)等等。 – Jay

1

您的工厂可以通过常规的多分派方法解析被简化。例如:

class DocumentValidatorFactory { 
    DocumentValidator forClass(Shipment shipment) { 
     new ShipmentDocumentValidator() 
    } 
    DocumentValidator forClass(Invoice invoice) { 
     new InvoiceDocumentValidator() 
    } 
} 

Groovy足够聪明,可以通过在运行时查看参数类来调用正确的方法。

1

Ditto WillP和Ataylor。让我补充一点,另一种选择是将验证器的创建放入要验证的类中。例如:

public interface Validation 
{ 
    public Validator getValidator(); 
} 
public class Shipment implements Validation 
{ 
    ... whatever ... 
    public Validator getValidator() 
    { 
    return new ShipmentValidator(); 
    } 
} 
public class Restock implements Validation 
{ 
    ... whatever ... 
    public Validator getValidator() 
    { 
    return new RestockValidator(); 
    } 
} 
public class ValidationFactory 
{ 
    public getValidator(Validation x) 
    { 
    return x.getValidator(); 
    } 
} 
+0

这是一个有效的解决方案,但是一旦你完成了这个工作,'ValidationFactory'会添加什么值?你永远不会有可以调用'ValidationFactory.getValidator(x)'的地方,你不能只调用'x.getValidator()'。我认为工厂的重点是能够将文档验证的所有知识与文档本身分开。 – ataylor

+0

它将CALLER所需的验证知识与实施分开。是的,被验证的事情必须知道他们的验证者是什么,而不是工厂知道他们的验证者是什么。 – Jay

+0

我有点像这个,非常OO,IMO。虽然我同意@ataylor的'ValidationFactory'现在有点没用。 “Java EE的bean验证”(http://www.javabeat.net/bean-validation-java-ee-creating-custom-constraints-validations/)中提供了一些自定义验证器''@Constraint(validatedBy = Clazz)' – Will