2016-02-05 125 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