I would like to create a DDD domain model library, to be used to any client. Where each client will provide default implementation of services.
My solution is something mixing Factory Method Pattern with Singleton:
1. domain-model.lib: Project structure:
1.1. domain-model.lib: Implementation:
User.class:
public class User {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
UserRepository.class:
public class UserRepository {
public User getUser(String id){
return UserDAOAbstractFactory.getInstance().getDefaultImplementation().read(id);
}
public void saveUser(User user){
UserDAOAbstractFactory.getInstance().getDefaultImplementation().insert(user);
}
}
UserDAO.class:
public interface UserDAO {
User read(String id);
void insert(User user);
void update(User user);
void delete(User user);
}
UserDAOAbstractFactory.class:
public abstract class UserDAOAbstractFactory implements Factory<UserDAO> {
private static UserDAOAbstractFactory instance;
public static UserDAOAbstractFactory getInstance() {
if(instance == null){
synchronized (UserDAOAbstractFactory.class) {
if(instance == null) {
throw new IllegalStateException("Cannot call getInstance() method before calling build() method");
}
}
}
return instance;
}
public static <T extends UserDAOAbstractFactory> void build(Class<T> clazz) {
if(instance == null){
synchronized (UserDAOAbstractFactory.class) {
if(instance == null) {
try {
instance = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
else{
throw new IllegalStateException("Factory already built. Cannot build twice.");
}
}
}
else{
throw new IllegalStateException("Factory already built. Cannot build twice.");
}
}
}
Factory.class:
public interface Factory<T> {
T getDefaultImplementation();
}
2. "Application 1" - Project structure:
2.2 "Application 1" - Implementation:
UserDAOFactoryMock.class
public class UserDAOFactoryMock extends UserDAOAbstractFactory {
private UserDAO userDAOMock = new UserDAO() {
final String USER_ID = "123";
User user;
@Override
public User read(String id) {
if(user.getId().equals(USER_ID)){
return user;
}
return null;
}
@Override
public void insert(User user) {
this.user = user;
this.user.setId(USER_ID);
}
@Override
public void update(User user) {
throw new UnsupportedOperationException();
}
@Override
public void delete(User user) {
throw new UnsupportedOperationException();
}
};
@Override
public UserDAO getDefaultImplementation() {
return userDAOMock;
}
}
UserDAOFactoryTest.class
public class UserDAOFactoryTest {
public UserDAOFactoryTest(){
UserDAOAbstractFactory.build(UserDAOFactoryMock.class);
}
@Test
public void insertReadUser_expectOK(){
User user = new User();
user.setName("Paulo");
UserRepository userRepository = new UserRepository();
// Insert User
userRepository.saveUser(user);
String userId = user.getId();
// Read user
User returnedUser = userRepository.getUser(userId);
// Check
assertTrue(user.getId().equals(returnedUser.getId()));
assertTrue(user.getName().equals(returnedUser.getName()));
}
}
My concern is, it is a good approach to use with the team? There is some anti-pattern?
Aucun commentaire:
Enregistrer un commentaire