Strategy pattern with return value - java

I try create Payment by strategy pattern. But All articles each I read look like this:
public interface PayStrategy {
void pay(BigDecimal paymentAmount);
}
But if I need return Single<RestResponse<PaymentResponse>>?Is this the right approach?
public interface PayStrategy {
Single<RestResponse<PaymentResponse>> pay(BigDecimal paymentAmount);
}
In any real system, the request for payment will return the result

I will suggest you to implement your problem statement in Generic return type like below:
public interface IPayStrategy<T> {
T Pay();
}
public class PayStrategy1 :IPayStrategy<int> {
public int Pay() { }
}
public class PayStrategy2 :IPayStrategy<String> {
public String Pay() { .. }
}
public class Context<T> {
private IPayStrategy<T> payStrategy;
public setStrategy(IPayStrategy<T> strategy) { this.payStrategy = strategy; }
public T doPayment() {
return payStrategy.Pay();
}
}

in my opinion it's right because it's up to you the definition of the contract, if you agree that all the strategies must return a result that is of type Single<RestResponse<PaymentResponse>> for me it's correct

Related

Java abstract factory pattern

I'm trying to build a customer email generator in java using the abstract factory pattern. I understand how to use the factory method pattern; however, I'm a bit confused about the abstract factory pattern. I'm trying to generate an email based on customer type. Could you look at my code below and tell me if I'm using the abstract method correctly? Thank you
public abstract class EmailTemplate {
public abstract String getHeader();
public abstract String getBody();
public abstract String getFooter();
public String generateEmail(){
return getHeader()+"\n"+getBody()+"\n"+getFooter();
}
}
public interface EmailFactory {
EmailTemplate createEmail();
}
public class BusinessEmail extends EmailTemplate {
#Override
public String getHeader() {
return "Dear [business customer],";
}
#Override
public String getBody() {
return "Thank you for being our valued customer. We are so grateful for the pleasure of serving you and hope we met your expectations.";
}
#Override
public String getFooter() {
return "Best Regards," +
"[name]";
}
}
public interface EmailGeneratorFactory {
EmailTemplate createEmail();
}
public class BusinessFactory implements EmailGeneratorFactory {
#Override
public EmailTemplate createEmail() {
return new BusinessEmail();
}
}
public class EMailGenerationSystem {
private static EMailGenerationSystem EMailGenerationSystem = new EMailGenerationSystem();
private EMailGenerationSystem(){};
public static EMailGenerationSystem getInstance(){
return EMailGenerationSystem;
}
public EmailTemplate getEmail(EmailGeneratorFactory factory){
return factory.createEmail();
}
}

Getters and Setters with interfaces has a parameter

How do i implement a getter and a setter method with interfaces as a parameter?
I have a class test that implements an Test interface but the interface has methods like this, that have other interfaces as methods.
public void setScoreStrategy(IScoreStrategy iScoreStrategy) {
}
public IScoreStrategy getScoreStrategy() {
return null;
}
public ITestStatistics getTestStatistics() {
return null;
}
public IQuestion getQuestion(int i) throws TestException {
return null;
}
The same way you deal with the regular fields in class:
Assumingv you have scoreStrategy and testStatistics fields:
public void setScoreStrategy(IScoreStrategy iScoreStrategy) {
this.scoreStrategy = scoreStrategy;
}
public IScoreStrategy getScoreStrategy() {
return scoreStrategy;
}
public ITestStatistics getTestStatistics() {
return testStatistics;
}
// ...

Interface segregation principle application

I'm wondering if the Interface segregation principle applys to my codebase.
Here's some example code:
First Class:
public class EntityGroup {
public List<Entity> tests;
//returns true if the EntityGroup is valid
public boolean validate() {
for (Entity test : tests) {
if (!test.validateFieldA() || !test.validateFieldB()) {
return false;
}
}
return true;
}
}
Second Class:
public abstract class Entity {
protected String fieldA;
public abstract boolean validateFieldA();
public abstract boolean validateFieldB();
}
Third Class:
public class EntityChild extends Entity {
private String fieldB;
#Override
public boolean validateFieldA() {
if (fieldA.equals("valid")) {
return true;
} else {
return false;
}
}
#Override
public boolean validateFieldB() {
if (fieldB.equals("valid")) {
return true;
} else {
return false;
}
}
}
Fourth Class:
public class EntityChild2 extends Entity {
#Override
public boolean validateFieldA() {
if (fieldA.equals("valid")) {
return true;
} else {
return false;
}
}
#Override
public boolean validateFieldB() {
return true;
}
}
This is a greatly simplified example from my real codebase but I think it illustrates the problem well. My EntityChild2 class is forced to implement a method it does not need or want to know about.
I know that it would be more correct to have a Interface that would contain the validateFieldB() method and only have EntityChild implement that interface.
With the understanding that this would take a significant amount of effort to refactor into this solution, I'm having a hard time justifying the time it would take to implement this solution in my real code base.
What potential problems will I run into down the line by leaving my code this way?
What benefits will I gain from refactoring my code to have a separate interface for validateFieldB()?
tldr: Why is the Interface Segregation Principle so important?
Wrong Abstraction
You make use of the interface segregation principle but with wrong abstractions.. Your different Entity-types differ only in they behavior.
Because of the shared behavior you have duplicate code in the methods validateFieldA of EntityChild and EntityChild2 . The method validateFieldB looks very similar to validateFieldA just the filed for checking the equality is an other.
You only need one Entity
Strategy Pattern
With the Strategy-Pattern you will have no duplicate code:
class EqualValidationStategy() implements ValidationStategy<T> {
#Override
public boolean check(T a, T b) {
return a.equals(b)
}
}
class TrueValidationStategy() implements ValidationStategy<T> {
#Override
public boolean check(T a, T b) {
return true;
}
}
Entity
public class Entity {
private String fieldA;
private String fieldB;
private ValidationStategy<String> validationForA;
private ValidationStategy<String> validationForB;
// all-args consturctor
#Override
public boolean validateFieldA() {
return validationForA.check(fieldA, "valid");
}
#Override
public boolean validateFieldB() {
return validationForB.check(fieldB, "valid");
}
}
// Validates fieldA and "ignores" fieldB
Entity example = new Entity(fieldA,
fieldB,
new EqualValidationStategy(),
new TrueValidationStategy());

Using a base enum as a default for dependent enums

I'm working on a client that uses a standardised web service, however one of the vendors behaves in a slightly different way such that we must take account of these behaviours. To do this we have been using an enum:
public enum ServiceProviderType {
FOO, BAR;
public ServiceProviderType checkService(String url) {
if (url.equals("http://www.example.com")) {
return ServiceProviderType.FOO;
} else {
return ServiceProviderType.BAR;
}
}
}
The difference in these behaviours also differ according to what we request from the service, eg we might request a layer and want that layer coloured red, but know that BAR and FOO services represent RGB values differently. To do this we've created another enum that stores the properties we want for each layer in the service.
public enum LayerServiceProviderType {
FOO("#ff0000"),
BAR("#ff5555");
private String colour;
public ServiceProviderType(String colour) {
this.colour = colour;
}
public String getColour() {
return colour;
}
public ServiceProviderType checkService(String url) {
if (url.equals("http://www.example.com")) {
return ServiceProviderType.FOO
} else {
return ServiceProviderType.BAR;
}
}
}
This works fine except for when we want to handle multiple layers and treat them as all being derivative of the same base enum. Essentially we want to handle Layer1ServiceProviderType.BAR as being equivalent to Layer2ServiceProviderType.BAR. But we can't subclass enums, and even attempting to do so seems to break all kinds of sound design principles.
My first thought was to have an interface which contains an enum:
interface ServiceProvider {
ServiceProviderType {FOO, BAR};
ServiceProviderType getServiceProviderType();
ServiceProvider checkService(String url);
}
public enum LayerServiceProvider implements ServiceProvider {
FOO (ServiceProviderType.FOO, "#ff0000"),
BAR (ServiceProviderType.BAR, "#ff0000");
public LayerServiceProvider(ServiceProviderType serviceProviderType, String colour) {
this.serviceProviderType = serviceProviderType;
this.colour = colour;
}
#Override
public ServiceProviderType getServiceProviderType() {
return this.serviceProviderType;
}
#Override
public ServiceProvider checkService(String url) {
if (url.equals("http://www.example.com")) {
return LayerServiceProviderType.FOO
} else {
return LayerServiceProviderType.BAR;
}
}
}
But it seems overwrought to me to have an enum with in an enum that each hold the same range of values. Is there a better way to do this?
Maybe the Visitor Pattern is what you're looking for.
Used with an enum, it basically allows adding enum-dependent logic without using switch statements.
Example:
public enum ServiceProviderType {
FOO {
#Override public <T> T apply(Action<T> action) { return action.doFoo(); }
},
BAR {
#Override public <T> T apply(Action<T> action) { return action.doBar(); }
};
public interface Action<T> {
T doFoo();
T doBar();
}
public abstract <T> T apply(Action<T> action);
public static ServiceProviderType checkService(String url) {
if (url.equals("http://www.example.com"))
return FOO;
return BAR;
}
}
public class LayerServiceProviderType implements ServiceProviderType.Action<String> {
#Override
public String doFoo() {
return "#ff0000";
}
#Override
public String doBar() {
return "#ff0000";
}
}
public class Main {
public static void main(String[] args) {
ServiceProviderType type = ServiceProviderType.checkService("");
String colour = type.apply(new LayerServiceProviderType());
}
}

data access object pattern with abstract factories, creation over generic types

I'm developing a database application for android devices.
First thing I need to do is creating the data access layer.
For this I want to use DAO-Pattern with abstract factories.
For all DAOs i have one Interface witch contains the declaration that all data object needs to implement. (in my case: IDataObject)
The specific DAOs are all represented by its own interface, extending the base interface of all DAOs.
base interface:
public interface IDataObject {
public IDataId getId();
public void write() throws MyDataWriteException;
public void validate() throws MyDataValidException;
}
a extensions:
public interface IDataSample1 extends IDataObject {
public void setNotice(String notice);
public String getNotice();
public void setDate(Date date);
public Date getDate();
}
To create an data object I want use abstract to use abstract factories, something like:
public interface IDataFactory<Template extends IDataObject> {
public List<Template> getAll();
public Template get(IDataId id);
public List<Template> getList(DataAccessArgument arg);
public List<Template> getList(List<DataAccessArgument> argList);
}
and the implementation:
public class DataSample1Fac implements IDataFactory<IDataSample1> {
public DataSample1Fac () {
}
public List<IDataSample1> getAll() {
return null;
}
public IDataSample1 get(IDataId id) {
return null;
}
public List<IDataSample1> getList(DataAccessArgument arg) {
return null;
}
public List<IDataSample1> getList(List<DataAccessArgument> argList) {
return null;
}
}
I don't get any error so far, but now I want to implement an factory builder:
public class DataFactoryBuilder {
private DataFactoryBuilder() {
}
public static<T extends IDataObject> IDataFactory<T> getFactory(){
if (T instanceof IDataSample1)
return new DataSample1Fac();
return null;
}
}
I get following errors(line 8):
T cannot be resolved to a variable
and (line 9)
Type mismatch: cannot convert from DataSample1Fac to IDataFactory<T>
Don't know how to fix this, any suggestions?
I would refactor Your's DataFactoryBuilder to something like that:
class DataFactoryBuilder {
private DataFactoryBuilder() {
}
public static IDataFactory<? extends IDataObject> getFactory(Class<? extends IDataObject> clazz){
if (IDataSample1.class.isAssignableFrom(clazz)) {
return new DataSample1Fac();
}
return null;
}
}
I got following solution:
public static <T extends IDataObject> IDataFactory<T> getFactory(Class<T> type) {
if (IDataSample1.class.isAssignableFrom(type)) {
DataSample1Facfac = new DataSample1Fac();
return (IDataFactory<T>) fac;
}
}
but i get an warning on: return (IDataFactory) fac;
Type safety: Unchecked cast from DataSample1Fac to IDataFactory<T>
I think that is not a problem, I just have to supress it

Categories

Resources