在我的项目中,我看到这样的界面。所有模型都扩展了界面。我想知道有什么用?
public interface IModel {
<T> T modelTo(Class<T> clazz);
}
public interface IPerson extends IModel {
public String getFirstName();
public void setFirstName(String firstName);
public String getMiddleName();
public void setMiddleName(String middleName);
}
然后在代码中的某些地方我看到了
@Override
public void modelJoin(IModel parent, IModel sample) {
//Some code
IPerson sample= sample.modelTo(IPerson.class);
IPerson person = parent.modelTo(IPerson.class);
//Some code
}
你能解释一下它的见解吗?
答案 0 :(得分:2)
看起来像是使用Adapter pattern。我们的想法是创建一个给定另一个类的类的“视图”,或者调整一种类作为另一个类。
一个简单的现实世界的例子可以是电插座。在不同的国家,使用不同类型的插座。因此,您使用适配器将手机插入通常无法“识别”的电源插座中。
当然,这可以使用面向对象编程和适配器模式进行建模。使用您的IModel接口,但命名为IAdaptable,它可以像这样使用。
public interface IAdaptable {
<T> T adaptAs(Class<T> clazz);
}
public interface IChargeAmerican { void chargePhoneInAmerica(); }
public interface IChargeEurope { void chargePhoneInEurope(); }
public class EuropeanSocket implements IAdaptable, IChargeEurope {
public <T> T adaptAs(Class<T> clazz) {
if (clazz.equals(IChargeAmerican.class)) {
return new EuropeanSocketToAmericanSocketAdapter(this);
}
throw new RuntimeException("unknown");
}
public void chargePhoneInEurope() {
;
}
}
public class AmericanSocket implements IChargeAmerican {
public void chargePhoneInAmerica() {
;
}
}
public class EuropeanSocketToAmericanSocketAdapter implements IChargeAmerican {
private EuropeanSocket socket;
public EuropeanSocketToAmericanSocketAdapter(EuropeanSocket socket) {
this.socket = socket;
}
public void chargePhoneInAmerica() {
socket.chargePhoneInEurope();
}
}
使用它可以简单地将欧洲插座改为美国插座,有点像在两者之间插入适配器。
public void foo() {
EuropeanSocket europe = new EuropeanSocket();
IChargeAmerican murica = europe.adaptAs(IChargeAmerican.class);
murica.chargePhoneInAmerica();
}
此示例显示adaptAs方法如何在两个接口IChargeAmerican和IChargeEurope之间创建链接。即使他们没有任何共同点,适配器也可以像他们一样行事。
现在,EuropeanSocket实现了IAdaptable接口,以便将自身“转换”为另一个已知套接字。通常虽然班级不应对此负责。正如维基百科上的例子所示,工厂或提供商更适合这一点。
答案 1 :(得分:1)
我认为你问为什么方法签名
<T> T modelTo(Class<T> clazz);
被使用。
参数clazz
用于在实现的方法中包含类型信息。然后,您可以非常轻松地访问类型信息。
然后,您可以创建一个对象,并从具有给定类的已实现方法返回它。
方法签名看起来有点笨拙但有用,因为编译后会丢失通用信息(类型擦除),参数使您可以访问类型信息(因此也可以访问预期的返回类型)。
答案 2 :(得分:0)
我可以想象,通过将Class对象作为调用modelTo(Class clazz)方法的其他方法的参数传递,或者换句话说:使用其他方法将IModel对象转换为任何方法,可以通过这种方式允许类型转换class甚至不知道他们将把它投入哪个类(甚至没有阻止将Class实例传递给这个甚至不是IModel的子类型的方法......)
知道如何实现这个modelTo方法会很有趣。抽象骨架类中是否有单个最终实现?它如何响应错误(例如将null作为clazz参数传递,或触发ClassCastException)?换句话说:这可能是尝试将所有类转换封装到单个方法中,用自定义异常或类似的东西替换ClassCastExceptions吗? (ClassCastException是一个RuntimeException,它可能是一种确保抛出已检查异常的方法,而不是在代码中的每个地方强制执行显式异常处理,我已经看到使用这种方法的项目...)