我是little library的作者,使用Mailgun service發送電子郵件。使用Java泛型設計轉換器SPI的正確方法
該庫目前有一個非常簡單的機制,可以使用某種HTML DSL生成豐富的郵件正文內容。我正在研究下一個版本,我希望提供一個轉換器SPI,以便您可以傳遞按需要格式化的對象。我正在考慮數字,日期,貨幣值等
我正在努力與泛型,通配符類型,範圍等。我認爲我的問題更多的是泛型設計的泛型使用的具體細節。所以我的問題是我應該如何設計我的SPI,因爲Java泛型的侷限性。
我已經開始定義轉換器接口:
public interface ContentConverter<T> {
String toString(T value);
}
有整個圖書館使用的配置對象。在那裏,用戶應該使用這種註冊方法來註冊該接口的實例。
public <T> Configuration registerConverter(ContentConverter<? super T> converter,
Class<T> classToConvert)
{
converters.add(new Converter<>(classToConvert, converter));
return this;
}
的Converter
類是一個內部類encapsule轉換器和它的類。
private final static class Converter<T> {
private Class<T> classOfConverter;
private ContentConverter<? super T> contentConverter;
Converter(Class<T> classOfConverter,
ContentConverter<? super T> contentConverter)
{
this.classOfConverter = classOfConverter;
this.contentConverter = contentConverter;
}
}
Configuration
保留轉換器列表。
private List<Converter<?>> converters = ...
最後,該配置提供按需轉換器。
@SuppressWarnings("unchecked")
public <T> ContentConverter<T> converter(Class<T> classToConvert) {
for (Converter<?> converter : converters)
if (classToConvert.isAssignableFrom(converter.classOfConverter))
return (ContentConverter<T>) converter.contentConverter;
return (ContentConverter<T>) defaultConverter;
}
默認轉換器只是撥打Object.toString()
。
private final static ContentConverter<Object> defaultConverter =
new ContentConverter<Object>() {
@Override
public String toString(Object value) {
return value.toString();
}
};
當用戶構建體消息,他可以調用任何這兩種方法來添加使用所配置的轉換器中的對象。
public Builder text(Object value) {
ContentConverter<?> converter = configuration.converter(value.getClass());
return text(value, converter);
}
public <T> Builder text(T value, ContentConverter<T> converter) {
return text(converter.toString(value));
}
public Builder text(String s) {
[...] // this is where the content is really appendend
return this;
}
但這不起作用。第一種方法不編譯。我嘗試過不同的組合,但我認爲問題更深入,關於類型的刪除。
這不會編譯,因爲需要強制轉換爲值 – Jorge
@Jorge值是T – wero
您是對的,我沒有看到您改變參數類型。 – Jorge