我们在项目中使用java.util.UUID的大量使用来识别ojbects并对它们进行操作,就像在这个接口中一样:
List<UUID> searchPerson(String text);
Person fetchPerson(UUID personUUID);
List<UUID> searchAdress(String text);
Person fetchAdress(UUID adressUUID);
Run Code Online (Sandbox Code Playgroud)
但是现在发生,是运行时错误的根源,是一个开发者无意中传递一个personUUID到fetchAdress方法,这是不应该的.
有没有办法让这种"类型安全"这样的帽子他不能通过fetchAdress方法传递一个personUUID?也许有一种方法可以使用泛型来做到这一点?
通过组合构建一个包含UUID功能的类,然后为您需要的每个"类型"UUID子类化它.
如果您不需要/想要子类上的完整UUID API,那么您可能会非常懒惰并且只需将其包装起来.像这样的东西:
public class MyUUID {
private UUID uuid;
public MyUUID() {
uuid = UUID.randomUUID();
}
public UUID getUUID() {
return uuid;
}
}
public class PersonUUID extends MyUUID { }
public class AddressUUID extends MyUUID { }
Run Code Online (Sandbox Code Playgroud)
如果手动解包以获取UUID对象会让您烦恼,只需在MyUUID上实现完整的UUID API并将每个调用委托给uuid成员.
好吧,因为你需要的只是一个类型化的 UUID,你可以使用泛型简单地创建一个接口.
package com.stackoverflow.q1747780;
public interface UUIDTyped<T>
{
public UUID value();
}
Run Code Online (Sandbox Code Playgroud)
现在假设Person和Address UUID是从不同的源创建的,您可以为每个源创建一个类,实现该接口.
package com.stackoverflow.q1747780;
import java.util.UUID;
public class UUIDFactory
{
public static class PersonUUID implements UUIDTyped<Person>{
/* (non-Javadoc)
* @see com.stackoverflow.q1747780.UUIDTyped#value()
*/
@Override
public UUID value() {
return UUID.randomUUID();
}};
public static class AddressUUID implements UUIDTyped<Address>{
/* (non-Javadoc)
* @see com.stackoverflow.q1747780.UUIDTyped#value()
*/
@Override
public UUID value() {
return UUID.randomUUID();
}};
public <T> UUIDTyped<T> newUUID() {
return new UUIDTyped<T>()
{
/**
* There is no difference on how Person and Address UUIDs are generated
*/
@Override
public UUID value() {
return UUID.randomUUID();
}
};
}
public UUIDTyped<Person> newPersonUUID(){
return new PersonUUID();
}
public UUIDTyped<Address> newAddressUUID(){
return new AddressUUID();
}
}
Run Code Online (Sandbox Code Playgroud)
概念证明
package com.stackoverflow.q1747780;
import junit.framework.Assert;
import org.junit.Test;
public class UUIDFactoryTest
{
@Test
public void testPersonUUID()
{
UUIDFactory uuidFactory = new UUIDFactory();
UUIDTyped<Person> newUUID = uuidFactory.newPersonUUID();
Assert.assertNotNull(newUUID.value());
}
@Test
public void testAddressUUID()
{
UUIDFactory uuidFactory = new UUIDFactory();
UUIDTyped<Address> newUUID = uuidFactory.newAddressUUID();
Assert.assertNotNull(newUUID.value());
}
}
Run Code Online (Sandbox Code Playgroud)
另外,你可以通过虚拟接口逃脱.
概念证明
package com.stackoverflow.q1747780;
import junit.framework.Assert;
import org.junit.Test;
public class UUIDFactoryTest
{
@Test
public void testNewUUID()
{
UUIDFactory uuidFactory = new UUIDFactory();
UUIDTyped<Person> newUUID = uuidFactory.newUUID();
UUIDTyped<Address> addressUUID = uuidFactory.newUUID();
Assert.assertNotNull(newUUID.value());
Assert.assertNotNull(addressUUID.value());
}
}
Run Code Online (Sandbox Code Playgroud)
最后你的服务就像
package com.stackoverflow.q1747780;
import java.util.List;
public interface Service<T>
{
public List< UUIDTyped<T> > search(String text);
public T fetch( UUIDTyped<T> uuid);
}
Run Code Online (Sandbox Code Playgroud)
使用PersonService类
package com.stackoverflow.q1747780;
import java.util.List;
public class PersonService implements Service<Person>
{
/* (non-Javadoc)
* @see com.stackoverflow.q1747780.Service#fetch(com.stackoverflow.q1747780.UUIDTyped)
*/
@Override
public Person fetch(UUIDTyped<Person> uuid) {
return null;
}
/* (non-Javadoc)
* @see com.stackoverflow.q1747780.Service#search(java.lang.String)
*/
@Override
public List< UUIDTyped<Person> > search(String text) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
和一个AddressService类
package com.stackoverflow.q1747780;
import java.util.List;
public class AddressService implements Service<Address>
{
/* (non-Javadoc)
* @see com.stackoverflow.q1747780.Service#fetch(com.stackoverflow.q1747780.UUIDTyped)
*/
@Override
public Address fetch(UUIDTyped<Address> uuid) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.stackoverflow.q1747780.Service#search(java.lang.String)
*/
@Override
public List<UUIDTyped<Address>> search(String text) {
// TODO Auto-generated method stub
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
测试PersonService的正确类型
package com.stackoverflow.q1747780;
import java.util.List;
import org.junit.Test;
public class PersonServiceTest
{
@Test
public void testFetch()
{
UUIDFactory uuidFactory = new UUIDFactory();
PersonService service = new PersonService();
Person person = service.fetch( uuidFactory.newPersonUUID() );
}
@Test
public void testSearch()
{
PersonService service = new PersonService();
List< UUIDTyped<Person> > uuidList = service.search("foo");
}
}
Run Code Online (Sandbox Code Playgroud)
测试AddressService的正确类型
package com.stackoverflow.q1747780;
import java.util.List;
import org.junit.Test;
public class AddressServiceTest
{
@Test
public void testFetch()
{
UUIDFactory uuidFactory = new UUIDFactory();
AddressService service = new AddressService();
Address address = service.fetch( uuidFactory.newAddressUUID() );
}
@Test
public void testSearch()
{
AddressService service = new AddressService();
List< UUIDTyped<Address> > uuidList = service.search("foo");
}
}
Run Code Online (Sandbox Code Playgroud)