public class ServiceFactory {
private static ServiceFactory instance;
private final DishService dishService = new DishService();
private final OrderService orderService = new OrderService();
private final UserService userService = new UserService();
private ServiceFactory() {
}
public static synchronized ServiceFactory getInstance() {
if (instance == null) instance = new ServiceFactory();
return instance;
}
public DishService getDishService() {
return dishService;
}
public OrderService getOrderService() {
return orderService;
}
public UserService getUserService() {
return userService;
}
}
It is just a simple class for getting objects, but it seems like a messed up with naming.
If not, what should be a proper name for such a class?
Since you are essentially accessing the same instance of a set of xxxxService instead of "constructing" new ones, it does not comply with the factory pattern.
Naming it SharedServices makes more sense, given that you made it a singleton, and that it shares various instances of services across the application.
Factory pattern works as follows:
An interface exists
public interface Foo {
String make(String someString);
}
and there are multiple implementations of that interface:
public class DishOrder implements Foo {
//constructor
String make(String someString) {-- custom implementation--}
}
public class DrinkOrder implements Foo {
//constructor
String make(String someString) {-- custom implementation--}
}
And then the factory exists:
public class OrderFactory {
private DishOrder dishOrder;
private DrinkOrder drinkOrder;
//constructor
public Foo getFoo(String type) {
if(type.equals("Dish"))
return DishOrder;
//and every other implementation of the interface
//can use switch here as well
}
}
Related
I am trying to implement Strategy pattern approach for payment processing in my Spring webflux based application.
My application supports multiple payment method like, Card Payment, Cash Payment, ...
Also, we have to support Square & Stripe for Card payment.
Model class,
// Model interface
public interface PaymentModel {
}
// Base model with attributes needed for all payment types
public class BaseModel implements PaymentModel {
private Float amount;
private Integer userId;
}
public class SquareCardModel extends BaseModel {
private String merchantId;
private String device;
private String orderId;
}
public class StripeCardModel extends BaseModel {
private String merchantId;
private String orderId;
}
public class CashModel extends BaseModel {
private String name;
private String orderId;
}
Service Class,
#Service
public interface PaymentService<T extends PaymentModel> {
Mono<ServerResponse> pay(T model);
String method();
}
#Service
public class CashPaymentService implements PaymentService<CashModel> {
private static final String PAYMENT_METHOD = "cash";
#Override
public Mono<ServerResponse> pay(CashModel model) {
// TODO Auto-generated method stub
return null;
}
#Override
public String method() {
return PAYMENT_METHOD;
}
}
#Service
public class SquarePaymentService implements PaymentService<SquareCardModel> {
private static final String PAYMENT_METHOD = "cash";
#Override
public Mono<ServerResponse> pay(SquareCardModel model) {
// TODO Auto-generated method stub
return null;
}
#Override
public String method() {
return PAYMENT_METHOD;
}
}
#Service
public class StripePaymentService implements PaymentService<StripeCardModel> {
private static final String PAYMENT_METHOD = "cash";
#Override
public Mono<ServerResponse> pay(SquareCardModel model) {
// TODO Auto-generated method stub
return null;
}
#Override
public String method() {
return PAYMENT_METHOD;
}
}
Factory Class,
#Service
public class PaymentFactory<T> {
private final List<PaymentService<? extends PaymentModel>> paymentServices;
#Autowired
public PaymentFactory(List<PaymentService<? extends PaymentModel>> paymentServices) {
this.paymentServices = paymentServices;
}
public PaymentService<? extends PaymentModel> retrievePaymentService(final String paymentMethod) {
Optional<PaymentService<? extends PaymentModel>> paymentService = paymentServices.stream()
.filter(service -> service.method().equals(paymentMethod)).findFirst();
if (paymentService.isEmpty()) {
throw new IllegalArgumentException("Unsupported Payment method ");
}
return paymentService.get();
}
}
User choose the payment method and the call comes to the backend,
#Transactional
public Mono<ServerResponse> payBilling(ServerRequest request) {
return request.bodyToMono(PaymentDto.class).flatMap(paymentReq -> {
if (paymentReq.getPaymentType().equals("CC")) { // For Card
return processCardPayment(usr, paymentReq);
} else {
return badRequest().bodyValue("Not supported yet !");
}
});
}
private Mono<? extends ServerResponse> processCardPayment(
PaymentDto paymentReq) {
PaymentService<PaymentModel> paymentService = (PaymentService<PaymentModel>) paymentFactory
.retrievePaymentService(paymentReq.getPaymentType());
PaymentModel paymentModel = buildPaymentModel((String) paymentReq.getPaymentType(), paymentReq,
jsonMap);
return paymentService.pay(paymentModel);
}
private PaymentModel buildPaymentModel(final String paymentMethod, final PaymentDto paymentReq,
if (paymentMethod.equals("squarePayment")) {
SquareCardModel model = new SquareCardModel();
model.setAmount(paymentReq.getTotal());
model.setMerchantId(paymentReq.getMerchantid());
model.setOrderId(orderId);
return model;
}
return null;
}
Questions:
Not sure if I have implemented generics properly with the strategy pattern.
Also, I dont like type casting here. (PaymentService). is there any better approach?
Why do I still need to use if for creating different model.
if (paymentMethod.equals("squarePayment")) {
PaymentService<PaymentModel> paymentService = (PaymentService<PaymentModel>) paymentFactory
.retrievePaymentService(paymentReq.getPaymentType());
PaymentModel paymentModel = buildPaymentModel((String) paymentReq.getPaymentType(), paymentReq,
jsonMap);
return paymentService.pay(paymentModel);
Here's a simplified version of your code which I think maintains what you need to do, from a type perspective:
import java.util.Optional;
public class App {
public interface PaymentModel { }
public static class CashModel implements PaymentModel { }
public interface PaymentService<T extends PaymentModel> {
void pay(T model);
void pay2(PaymentModel model);
}
public static class PaymentFactory {
public PaymentService<PaymentModel> retrievePaymentService(final String paymentMethod) {
Optional<PaymentService<PaymentModel>> paymentService = null;
return paymentService.get();
}
public PaymentService<? extends PaymentModel> retrievePaymentService2(final String paymentMethod) {
Optional<PaymentService<PaymentModel>> paymentService = null;
return paymentService.get();
}
}
public static void main(String... args) throws NoSuchFieldException, IllegalAccessException {
PaymentFactory paymentFactory = null;
PaymentService<PaymentModel> paymentService = paymentFactory
.retrievePaymentService("foo");
paymentService.pay(new CashModel());
PaymentService<? extends PaymentModel> paymentService2 = paymentFactory
.retrievePaymentService2("foo");
paymentService2.pay(new CashModel()); // error
paymentService2.pay2(new CashModel()); // ok
}
}
Look at the difference between retrievePaymentService and retrievePaymentService2.
retrievePaymentService returns PaymentService<PaymentModel> which says that it is a payment service which works on any PaymentModel implementation.
retrievePaymentService2 returns PaymentService<? extends PaymentModel> which says that it is a payment service which works on some specific, unknown PaymentModel implementation.
As you have already made sure that your PaymentModel type matches the PaymentService you are getting from the factory, the first form is what you want.
A better design might try to not have two parallel class hierarchies which need to be matched up carefully at runtime.
Also, processCardPayment seems as though it should handle all PaymentModels?
I want to write test class using mockito to test stateless local ejb with interface.
public class SampleHandler{
private static final Logger logger = Logger.getLogger(TLDHandler.class);
#EJB
private IMsAgent msAgent;
public void setMsAgent(IMsAgent msAgent) {
this.msAgent = msAgent;
}
public infoAvailability checkInfoAvailable(String sample){
final URI url = msAgent.buildUrl(API_PREPEND_URL + sample + "/check");
}
}
#Stateless
#Local({IMsAgent.class})
public class MsAgentImpl implements IMsTokenAgent {
private static final String API_BASE_URL_PROPERTY_NAME = "API_BASE_URL";
private static final String DEFAULT_API_BASE_URL = "https://stage.url.com/v1";
private static Preferences preferences = Preferences.systemNodeForPackage(MsAgentImpl.class);
#Override
public URI getBaseUrl() {
return URI.create(preferences.get(API_BASE_URL_PROPERTY_NAME, DEFAULT_API_BASE_URL));
}
}
My Test Class
#RunWith(MockitoJUnitRunner.class)
public class sampleTest {
#Mock
IMsAgent msAgent;
#InjectMocks
private SampleHandler sampleHandler = new SampleHandler();
#Before
public void setUp() {
sampleHandler.setMsAgent(Mockito.mock(MsAgentImpl.class));
}
#Test
public void checkInfoTest() throws Exception {
final infoAvailability response = sampleHandler.checkInfoAvailable("sample");
}
}
When I run checkInfoTest method from sampleTest class control goes to SampleHandler class. In that class url variable always return null value.
After debug my code it is never goes to MsAgentImpl.getBaseUrl method.
I have an abstract class that contains common methods:
public abstract class AbstractDAO<T> implements IFindTradeDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public List<Trade> findOne(final int eventId) {
return jdbcTemplate.query(getOneQuery(), new Object[]{eventId}, new RowMapper());
}
#Override
public List<Event> getAll() {
return jdbcTemplate.queryForList(getAllQuery(), Event.class);
}
protected abstract String getOneQuery();
protected abstract String getAllQuery();
}
The derived class which provides type specific queries:
#Repository
public class TypeA extends AbstractDAO implements IFindTradeDAO {
private static final String FIND = "sql/findA.sql";
private static final String GET = "sql/getA.sql";
#Override
protected String getOneQuery() {
return FIND;
}
#Override
protected String getAllQuery() {
return GET;
}
#Repository
public class TypeB extends AbstractDAO implements IFindTradeDAO {
private static final String FIND = "sql/findB.sql";
private static final String GET = "sql/getB.sql";
#Override
protected String getOneQuery() {
return FIND;
}
#Override
protected String getAllQuery() {
}
}
Given I have this class structure, I want to invoke the getAllQuery() for all the derived class sql e.g. for TypeA and TypeB on schedule using
org.springframework.scheduling.annotation.Scheduled;
#Component
public class GetAllEvents {
#Scheduled
public void processUnprocessedEvents() {
//invoke getAllQuery for all DAOS and combine results
}
}
I am not quite sure how I can derive a Component that will invoke all? Is there technique or example I can use to achieve this?
I'm not a Java programmer, but in .NET you'd need to put them all into some type of list or array, and call the function on each item.
So maybe create a method called Add(IFindTradeDAO dao) which adds each one to a list. And then call the method on each of those items.
I am trying to use inheritence and generics to create my application, but it doesn't seem to work the way I expect it to. I'll show you what I mean (TL;DR at the bottom):
public interface IModel extends Serializable {
public int save();
public void update();
public void delete();
}
// <T> is a JPA annotated entity/class
#SuppressWarnings("serial")
public abstract class Model<T> implements IModel {
private final Repository<T> _repository;
protected T _entity;
public Model(T entity, Repository<T> repository) {
this._entity = entity;
this._repository = repository;
}
public int save() {
return _repository.save(_entity);
}
...
}
This is implemented in for example my AccountModel, which is a Model with generic Account (which is a JPA entity) and which implements IAccount.
public class AccountModel extends Model<Account> implements IAccount {
private static final AccountRepository REPOSITORY = new AccountRepository();
public AccountModel(Account entity) {
super(entity, REPOSITORY);
}
// Method implementations...
}
My generic Repository looks like this:
public abstract class Repository<T> implements Serializable {
private static SessionFactory SESSION_FACTORY;
private final Class<T> _repositoryClass;
private static boolean _initiated = false;
public Repository(Class<T> repositoryClass) {
if (!Repository._initiated)
setup();
this._repositoryClass = repositoryClass;
}
private void setup() {
// logics
Repository._initiated = true;
}
public final Model<T> getById(int id) {
Session session = SESSION_FACTORY.openSession();
try {
session.beginTransaction();
T t = session.get(_repositoryClass, id);
return new Model<T>(t, this); // As suggested by #Vlad
}
finally {
session.close();
}
}
}
The account implementation of this abstract Repository is:
public class AccountRepository extends Repository<Account> {
public AccountRepository() {
super(Account.class);
}
public Model<Account> getByEmail(String emailAddress) {...}
}
So far so good, this is all working as expected. But I cannot use a Model<T> as a TModel.
TL;DR
I would like use the following line of code:
AccountModel account = new AccountRepository().getById(1);
Since AccountModel inherits Model<Account> and new AccountRepository().getById() always returns Model<Account> I expect this to work, but it doesn't.
What am I missing?
I am trying to write a Singleton Lazy Loading Pattern. Here is the class:
public class IMDBLookup {
private static class LazyLoad {
private static final IMDBLookup IMDB_LOOKUP;
static {
IMDB_LOOKUP = new IMDBLookup();
}
}
public static IMDBLookup getInstance() {
return IMDBLookup.LazyLoad.IMDB_LOOKUP;
}
}
I am wondering whether or not I am doing it in a right way?
Thanks in advance.
I prefer to use enum for simplicity.
public enum IMDBLookup {
INSTANCE;
// add fields and methods here.
}
That is correct. You may want to simplify the inner (holder) class as private static final IMDBLookup IMDB_LOOKUP = new IMDBLookup(); for brevity (to get rid of the static initializer block.)
public class IMDBLookup {
private IMDBLookup(){
// without this I do not get why is it a singleton
// anyone could create instances of your class by the thousands
}
private static class LazyLoad {
private static final IMDBLookup IMDB_LOOKUP;
static {
IMDB_LOOKUP = new IMDBLookup();
}
}
public static IMDBLookup getInstance() {
return IMDBLookup.LazyLoad.IMDB_LOOKUP;
}
}
and you should probably use an enum (not completely sure I do this right)
public class IMDBLookup {
private IMDBLookup(){
}
private static enum LazyLoad {
IMDB_LOOKUP_INSTANCE;
private static final IMDB_LOOKUP = new IMDBLookup();
}
public static IMDBLookup getInstance() {
return LazyLoad.IMDB_LOOKUP_INSTANCE.IMDB_LOOKUP;
}
}
The advice you to think about clone & serialize
import java.io.Serializable;
public class DBConnectionInner implements Cloneable, Serializable {
private static final long serialVersionUID = 1173438078175185035L;
#Override
protected Object clone() throws CloneNotSupportedException {
return new CloneNotSupportedException("CLONE NOT SUPPORT FOR SINGTELTON");
}
protected Object readResolve() {
return getInstance();
}
private DBConnectionInner() {}
static DBConnectionInner getInstance() {
System.out.println("DBConnectionInner getInstance");
return LazyInit.instance;
}
public static class LazyInit {
private static final DBConnectionInner instance = new DBConnectionInner();
}
}