Im trying to make a small DSL in Java that I can use to populate testdata in a database. The language I would like to use is as follows.
createRowInTableA().
createRowInTableB().
createRowInTableA().
createRowInTableB().
createRowInTableC().
end();
The order the tables are created is important, for example tableB depends on tableA and tableC depends on tableA and tableB. Therefore I want to make it so that the option to create tableB only is available directly after tableA is created etc. I have started to create the interfaces describing the DSL but I don't know how I should actually implement the interfaces inorder to make the type of nested behavior I'm looking for. This is what the interfaces looks like.
public interface End {
public void sendTestData();
}
public interface TableA extends End {
public Builder createRowInTableA();
}
public interface TableB extends TableA {
public Builder createRowInTableB();
}
public interface TableC extends TableB {
public Builder createRowInTableC();
}
However when I start implementing this language using builder pattern to create a fluent API the hierarchy I want goes away.
public class DBBuilder implements TableC {
static class Builder {
public Builder createRowInTableA(){...}
public Builder createRowInTableB(){...}
public Builder createRowInTableC(){...}
}
}
You can use a set of interfaces and class adapters:
public interface canCreateTableAIf{
public DBBuilderB createRowInTableA()
}
public interface canCreateTableBIf{
public DBBuilderC createRowInTableB()
}
public interface canCreateTableCIf{
public DBBuilderD createRowInTableC()
}
public class canCreateTableA implements canCreateTableAIf (){
public DBBuilderB createRowInTableA(){
...
}
}
public class canCreateTableB implements canCreateTableBIf (){
public DBBuilderC createRowInTableB(){
...
}
}
public class DBBuilderRoot extends canCreateTableA {
}
public class DBBuilderB extends canCreateTableB {
}
public class DBBuilderBCD extends canCreateTableB,canCreateTablec,canCreateTableD {
}
This is not so complicated. But I would check if there is a better way than using fluent Builders. Java 8 for example offers closures. Hier is my suggestion. I've not compiled and tested it. The idea should work but there might be syntax errors.
public class ABuilder
{
private BBuilder subBuilder;
public ABuilder()
{
subBuilder = new BBuilder(this);
}
public BBuilder createRowForA()
{
// your code
return this.subBuilder;
}
public void end()
{
// send test data
}
}
x
public class BBuilder
{
private ABuilder parentBuilder;
private CBuilder subBuilder;
public BBuilder( ABuilder parentBuilder )
{
this.parentBuilder = parentBuilder;
this.subBuilder = new CBuilder(this);
}
public CBuilder createRowForB()
{
// your code
return this.subBuilder;
}
public ABuilder end()
{
return this.parentBuilder;
}
}
x
public class CBuilder
{
private BBuilder parentBuilder;
public CBuilder( BBuilder parentBuilder )
{
this.parentBuilder = parentBuilder;
}
public CBuilder createRowForC()
{
// your code
// I Assume you want to be able to write more than 1 C-row
return this;
}
public BBuilder end()
{
return this.parentBuilder;
}
}
Then you can do:
(new ABuilder())
.createRowForA()
.createRowForB()
.createRowForC()
.end()
.end()
.end();
(new ABuilder())
.createRowForA()
.createRowForB()
.end()
.createRowForB()
.createRowForC()
.end()
.end()
.end();
I'm sure you see more exmples. ;-)
Related
I have multiple services that implement interface with one method - execute(). Each service uses this method to execute some actions based on a String value, which, in original code, is enum, so those values are constants.
interface Service{
public void execute();
}
class Service1 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething(payload);
}
}
}
class Service2 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething1(payload);
}
if(payloadType.equals("type2")){
doSomething2(payload);
}
}
}
I want to avoid writing same if statements each time I create a new Service. Problem is, that each Service doesn't have to execute actions based on each string types. So Service1 executes action when type is equal to "type1", however Service2 executes actions based on "type1" and "type2".
I tried following solution:
class Main {
public static void main(String[] args) {
exec(new B(), "type2");
}
private static void exec(Service service, JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
Init i = (Init)service;
i.init(payload);
}
if(payloadType.equals("type2")){
Action a = (Action)service;
a.action(payload);
}
}
}
interface Service{
}
interface Init{
public void init(JSONObject payload);
}
interface Action{
public void action(JSONObject payload);
}
class A implements Service, Init{
#Override
public void init(JSONObject payload){
doSomething(payload);
}
}
class B implements Service, Init, Action{
#Override
public void init(JSONObject payload){
doSomething1(payload);
}
#Override
public void action(JSONObject payload){
doSomething2(payload);
}
}
The above code works, but I don't like using casting. I think it's not a good practice, also very unsafe. Could you suggest, what design pattern or other solution could I use here? I tried visitor, but I couldn't figure out the right implementation with this case.
UPDATE
Thanks for all the answers, they were very helpfull. I managed to achieve what I was looking for. Here's the code that finally works.
public class Main {
public static B b = new B();
public static A a = new A();
public static void main(String[] args) {
exec(b, "init");
}
private static void exec(Service service, String type){
if(type.equals("init") && service instanceof Init){
service.fillCarrier(new InitCarrier());
}
if(type.equals("action") && service instanceof Action){
service.fillCarrier(new ActionCarrier());
}
}
}
interface Carrier<T>{
public void set(T t);
}
class InitCarrier implements Carrier<Init>{
public void set(Init init){
init.init();
}
}
class ActionCarrier implements Carrier<Action>{
public void set(Action action){
action.action();
}
}
abstract class Service{
public void fillCarrier(Carrier carrier){
carrier.set(this);
}
}
interface Init{
public void init();
}
interface Action {
public void action();
}
class A extends Service implements Init{
#Override
public void init(){
System.out.println("init a");
}
}
class B extends Service implements Init, Action{
#Override
public void init() {
System.out.println("init b");
}
#Override
public void action(){
System.out.println("action");
}
}
To achieve this requirement, we need to pattern.
Factory pattern.
Strategy pattern.
TypeFactory creates an object based on the string we delivered. Each Type implementation implements a doSomething() method in its own way. (factory pattern is used here)
Type Strategy:
interface Type{
public void doSomething();
}
class TypeOne implements Type{
#Override
public void doSomething() {
System.out.println("Type One!");
}
}
class TypeTwo implements Type{
#Override
public void doSomething() {
System.out.println("Type Two!");
}
}
Type Factory:
class TypeFactory{
Type type;
public Type createType(String condition) {
if (condition == null || condition.isEmpty()) {
return null;
}
if ("type1".equals(condition)) {
return new TypeOne();
}
else if ("type2".equals(condition)) {
return new TypeTwo();
}
return null;
}
}
Now to achieve the final goal, we need to declare a Service interface with an execute method. This execute method takes Type as an input parameter. Based on which type you actually pass, the corresponding doSometing method will be invoked. (strategy pattern used only)
interface Service{
public void execute(Type type);
}
class ServiceOne implements Service{
#Override
public void execute(Type type) {
System.out.print("Service One - ");
type.doSomething();
}
}
class ServiceTwo implements Service{
#Override
public void execute(Type type) {
System.out.print("Service Two - ");
type.doSomething();
}
}
Main Class looks like this:
public class DesignPatternCombo {
public static void main(String[] args) {
Type typeOne = new TypeFactory().createType("type1");
Type typeTwo = new TypeFactory().createType("type2");
Service serviceOne = new ServiceOne();
serviceOne.execute(typeOne);
Service serviceTwo = new ServiceTwo();
serviceTwo.execute(typeOne);
serviceTwo.execute(typeTwo);
}
}
Expected output:
Service One - Type One!
Service Two - Type One!
Service Two - Type Two!
Tricky question, I may have a solution that could work.
That would be to store the Types, with the code that type does in the form of a HashMap.
HashMap<String, Function<Void, Void>> types = new HashMap<String, Function<Void, Void>>();
Then in the main function, you would fill up the HashMap with the names of the types, and the function it runs.
types.put("Type1",()->{
/*Do something*/
});
types.put("Type2",()->{
/*Do something*/
});
types.put("Type3",()->{
/*Do something*/
});
Then in the Service, you would have an array of Strings for what types it uses. Such as:
String[] serviceTypes = {"Type1", "Type2"};
Finally, in the execute function of the Service you would run the corresponding lambda to the string.
public void execute(String type){
if((new ArrayList<>(Arrays.asList(serviceTypes))).contains(type)) {
Main.types.get(type);
}
}
You might work with an abstract base class.
The base class implements Service and has the execute() method. It does not get around if statements, but after all it could have a list of allowed values, and as soon as the type parameter is contained in the list it would call another method. Per default the method does nothing.
Concise subclasses of the base no longer need to perform the if conditions as they simply override the single methods in the base class. So this works for a whole bunch of quite similar services.
The advantage of this approach is if you have some exotic, incompatible type of service you can skip the if statements by directly overwriting the execute() method. So that pattern is extensible, which is probably worth more than saving a few more if statements.
You can solve this elegantly with the Strategy Design Pattern.
Create a common interface called Strategy
interface Strategy {
void execute(JSONObject payload);
}
Create multiple implementations of Strategy according to your needs:
class ServiceType1 implements Strategy {
//constructors and fields
#Override
public void execute(JSONObject payload) {
//code to be executed for "type1"
}
}
class ServiceType2 implements Strategy {
//constructors and fields
#Override
public void execute(JSONObject payload) {
//code to be executed for "type2"
}
}
...
Group the Service implementations by type, eg.:
Map<String, Strategy> strategyMap = new HashMap<>();
strategyMap.put("type1", new ServiceType1());
strategyMap.put("type2", new ServiceType2());
...
Invoke the desired Service without the need for any if statements, like this:
private static void exec(String payloadType, JSONObject payload) {
strategyMap.get(payloadType).execute(payload);
}
P.S.: if all implementations of Strategy share some common behaviour, you can convert Strategy from interface to abstract class and move the common behaviour there.
wow, your architecture seems much complex. you should consider better hierarchy. but if you can't, why don't you just make a method on Service and let the subtype decide what behavior they want. Then you can call that method from Service to execute
static class Main {
public static void main(String[] args) {
exec(new B());
}
private static void exec(Service service){
service.execute();
}
}
interface Service{
void execute();
}
interface Init{
public void init();
}
interface Action{
public void action();
}
static class A implements Service, Init{
#Override
public void init(){
System.out.println("init a");
}
#Override
public void execute(){
init();
}
}
static class B implements Service, Init, Action{
#Override
public void init(){
System.out.println("init b");
}
#Override
public void action(){
System.out.println("action");
}
#Override
public void execute(){
action();
}
}
What about extracting common logic to the separate class. It cloud be:
BaseService and all other services should implement this one;
ServiceDelegate and all other services should delegate all work to this one.
The below snippet provides the first solution.
// This is you Service interface
public interface Service {
void execute(JSONObject payload, String payloadType);
}
// This is base implementation. Use `Map` to replace `if` statements
public abstract class BaseService implements Service {
private static final Consumer<JSONObject> NULL = jsonObject -> { };
private final Map<String, Consumer<JSONObject>> consumers;
protected BaseService(Map<String, Consumer<JSONObject>> consumers) {
this.consumers = consumers == null || consumers.isEmpty() ? Map.of()
: Collections.unmodifiableMap(consumers);
}
#Override
public final void execute(JSONObject payload, String payloadType) {
consumers.getOrDefault(payloadType, NULL).accept(payload);
}
}
public class ConcreteService extends BaseService {
private static final Consumer<JSONObject> DO_SOMETHING_TYPE1 = jsonObject -> {
// TODO implementation for "type1"
};
private static final Consumer<JSONObject> DO_SOMETHING_TYPE2 = jsonObject -> {
// TODO implementation for "type2"
};
public ConcreteService() {
super(Map.of(
"type1", DO_SOMETHING_TYPE1,
"type2", DO_SOMETHING_TYPE2));
}
}
I have these classes:
#Data
#AllArgsConstructor
#NoArgsConstructor
public class User {
private String name;
private int age;
}
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Admin {
private String name;
private int age;
}
And I have some operations with template method pattern implementation. Base class with algorithm:
public abstract class Operation<T> {
public void process(T t) {
System.out.println(t);
updateName(t);
System.out.println(t);
}
protected abstract void updateName(T t);
}
Two children with implementation template method:
#Component
public class UserOperation extends Operation<User> {
#Override
protected void updateName(User user) {
String newName = user.getName().toUpperCase();
user.setName(newName);
}
}
#Component
public class AdminOperation extends Operation<Admin> {
#Override
protected void updateName(Admin admin) {
String name = admin.getName();
StringBuilder builder = new StringBuilder();
builder.append(name);
StringBuilder reverse = builder.reverse();
admin.setName(reverse.toString());
}
}
My questions:
How do I rewrite this code to use composition?
Do I understand correctly that when using the template method, I attach to inheritance?
The template method is a great way to avoid duplication. But if it binds me to inheritance, what other ways are there to avoid code duplication? In my example, how can I use composition? (replace the template method with something else?)
1) How do I rewrite this code to use the composition?
The Strategy Pattern is one way. Essentially, you would reverse the relationship between data and operations by passing the operations into the data rather than passing the data into the operations. This is a fundamental change, because "real" objects (with state and behavior) are used instead of data classes.
2) Do I understand correctly that when using the template method, I attach to inheritance?
Yes, the Template Method Pattern is fundamentally based on inheritance.
Instead of template pattern you could have a proxy:
public abstract class Operation<T> {
public abstract void updateName(T t);
}
public class OperationProxy<T> extends Operation<T> {
private final Operation<T> delegate;
public OperationProxy(Operation<T> delegate) {
this.delegate = delegate;
}
#Override
public void updateName(T t){
System.out.println(t);
delegate.updateName(t);
System.out.println(t);
}
}
Note that this would allow you to make class Operation and interface.
UPDATE
Another possibility is defining sequences of operations, and a print operation (even more code):
public interface Operation<T> {
void updateName(T t);
}
public class OperationSequence<T> implements Operation<T> {
private final Operation<T>[] steps;
public OperationSequence(Operation<T>... steps) {
this.steps = steps;
}
#Override
public void updateName(T t){
for (Operation<T> step: steps) {
step.updateName(t);
}
}
}
public class PrintOperation<T> implements Operation<T> {
#Override
public void updateName(T t){
System.out.println(t);
}
}
You can now use the following code:
Operation<MyClass> print = new PrintOperation<>();
Operation<MyClass> seq = new OperationSequence<>(
print, (t) -> {doSomethingWith(t);}, print);
Assume I have an interface with a class embedded in it (the purpose being that this interface must provide a 'type'. The interface has some methods using that 'type'. So, in file S.java, I have
public interface S {
public class SType
{
}
public abstract void f( SType a );
}
I want to implement this interface, and I try this, in file SS.java:
public final class SS implements S
{
public class SType extends java.util.HashSet<Integer>
{
}
public void f( SType a )
{
// ...
}
}
However, when I try to compile these files ("javac S.java SS.java"), I get the usual error message "SS is not abstract and does not override abstract method f(SType) in S" indicating that "f()" in the concrete class is not a proper implementation of "f()" in the interface. Why?
Try with:
public final class SS implements S{
public class SType extends java.util.HashSet<Integer>
{
}
public void f(S.SType a) {
// ..
}
}
EDIT:
Perhaps, you need this:
public interface S<SType> {
public void f( SType a );
}
public final class SS implements S<HashSet<Integer>> {
public void f(HashSet<Integer> a ){
// ...
}
}
I created a builder for a lookup table and using it as shown below.
public class RaceCodeDataBuilder {
private RaceCode raceCode;
public RaceCodeDataBuilder() {
raceCode = new RaceCode();
}
public RaceCodeDataBuilder code(String code) {
raceCode.setCode(code);
return this;
}
public RaceCodeDataBuilder displayName(String displayName) {
raceCode.setDisplayName(displayName);
return this;
}
public RaceCode build() {
return raceCode;
}
}
Using this builder in a test:
RaceCode mockRaceCode = new RaceCodeDataBuilder()
.code("2054-5")
.displayName("Black or African American")
.build();
I am expecting lot more similar builders for other look up tables such as StateCodeBuilder, GenderCodeBuilder and all of them have just "code" and "displayName", similar to above builder.
I want to create a generic builder and avoid creating several builder classes doing the same job with different name.
I attempted something in generics but I am way off..
public class CodeDataBuilder<T>{
private T t;
public CodeDataBuilder(T t) {
this.t = t;
}
public CodeDataBuilder code(String code) {
raceCode.setCode(code); // Cant write T.setCode here for obvious resons
return this;
}
public CodeDataBuilder displayName(String displayName) {
raceCode.setDisplayName(displayName); // Cant write T.setDisplayNamehere for obvious resons
return this;
}
public T build() {
return t;
}
}
Can someone help me with that?
Thank you.
Create an interface BuildableCodeData with the methods you need, and implement it with classes like RaceData.
Your code will then look like:
public interface BuildableCodeData {
public void setCode(String code);
public void setDisplayName(String name);
}
public class Builder<T extends BuildableCodeData> {
private T codeData;
public Builder(T codeData) {
this.codeData = codeData;
}
public Builder<T> setCode(String code) {
codeData.setCode(code);
return this;
}
public Builder<T> setDisplayName(String displayName) {
codeData.setDisplayName(displayName);
return this;
}
public T build() {
return codeData;
}
}
It looks more like you should use an interface, and just make your build method return that interface. For example:
public interface Buildable{
void setDisplayName(String name);
void setCode(String code);
}
public class CodeDataBuilder {
private Buildable mObj;
public CodeDataBuilder(Buildable mObj) {
this.mObj = mObj;
}
public CodeDataBuilder code(String code) {
mObj.setCode(code); // Cant write T.setCode here for obvious resons
return this;
}
public CodeDataBuilder displayName(String displayName) {
mObj.setDisplayName(displayName); // Cant write T.setDisplayNamehere for obvious resons
return this;
}
public Buildable build() {
return mObj;
}
}
}
Then just make any object you want to build implement the Buildable interface.
If you create an interface with the needed methods:
interface CodeModel {
public void setCode(String s);
public void setDisplayName(String s);
}
You can then ask your generic class to accept only T extends CodeModel, like so:
class CodeDataBuilder<T extends CodeModel> {
// T has setCode method now!
}
Hope this helps!
If you have an interface with some standard functions, you can create a generic builder for it. The base builder would be abstract, and for each concrete implementation, there would be a concrete builder.
Interface:
public interface CodeNameable {
String getCode();
String getName();
}
Concrete implementation:
public class CodeNamedCar implements CodeNameable {
private String code;
private String name;
public CodeNamedCar(String code, String name) {
this.code = code;
this.name = name;
}
}
Abstract builder:
public abstract class CodeNameBuilder<C extends CodeNameable> {
public String code;
public String name;
public CodeNameBuilder() {
}
}
Concrete builder:
public abstract class CarBuilder extends CodeNameBuilder<CodeNamedCar> {
public CarBuilder() {
}
public CarBuilder code(String co_de) {
this.code = code;
return this;
}
public CarBuilder name(String name) {
this.name = name;
return this;
}
public CodeNameCar build() {
return (new CodeNameCar(code, name));
}
}
Then you can use it as you hoped:
CodeNamedCar car = new CarBuilder().code("thecode").name("Mazda").build();
Using this design, you'll need to check each field for correctness (non-null and non-empty, for example) in the CodeNameCar constructor. There are other ways to design it, too.
The builder pattern is about to crate a new instance of class and initialize it as much as required to do.
In the way you are going you tend to finish with a partial setter of some properties and create a possible fake relation because two object has the same attributes.
To support this in example everything has an name attribute but you do not create a super interface to called Nameable and implements its in every possible place.
If those attribute are shared across your classes you should think to create a class for them.
class Code {
int number;
String name;
}
class Race {
Code code;
//other attributes;
}
Then you have a one builder for code and another for race.
Note also that the good design is a balance of trade offs. If two fields are common for 5 classes is the a purpose to make the code complex and create a dedicated mechanize that will only pack the initialization and will not do anything productive.
The java compiler allows me write a Class definition inside an Interface . Are there any specific uses of this ?
interface ClassInterface {
void returnSomething();
int x = 10;
class SomeClass {
private int y;
private void classDoingSomething() {
}
}
}
Please explain .
The uses are the same that a class nested in another class: it allows scoping the class to the interface. You could imagine something like this:
public interface Switch {
public enum Status {
ON, OFF;
}
void doSwitch();
Status getStatus();
}
It avoids defining a top-level class named SwitchStatus (because Status could be a too generic name).
Yes Java allows you to define an inner class inside an interface One use I can think of is tightly binding a certain type (defined by the class) to an interface and perhaps limit access only to the interface methods. There's an example of such use on here
I use that pattern to embed multiple tiny concrete implementations that share a large amount of commonality. It's easier to manage 25 tiny extensions of the same abstract class within the same file. Using like in C# namespace enclosure.
/**
* Dao 道 = access/way/avenue
* Bao 包 = bundle/package/
*/
public interface DaoBao {
public abstract class <E extends BlessedEntity> BlessedDaoWager<E,T> {
private JdbcTemplate jtmpl;
public void setDatasource(Datasource ds) {
this.jtmpl = new JdbcTemplate(ds);
}
public E find(BlessedKey key) {
blah .. blah .. blah ...
}
public List<E> list(Date from, Date to) {
blah .. blah .. blah ...
}
public boolean remove(BlessedKey key) {
blah .. blah .. blah ...
}
public T getKey(E ent) {
return ent.getId();
}
}
public class BlessedEmployeeDao
extends BlessedDaoWager<BlessedEmployeeEntity, Long> {
public Long getKey(BlessedEmployeeEntity ent) {
return ent.getCucurucucu();
}
}
public class BlessedSalaryDao
extends BlessedDaoWager<BlessedSalaryEntity, BlessedEmployeeEntity> {
public BlessedEmployeeEntity getKey(BlessedSalaryEntity ent) {
return ent.getEmployeeId();
}
}
public class BlessedHoursDao
extends BlessedDaoWager<BlessedHoursEntity, BlessedEmployeeEntity> {
public BlessedEmployeeEntity getKey(BlessedSalaryEntity ent) {
return ent.getEID();
}
}
public class BlessedGooDao
extends BlessedDaoWager<BlessedGooEntity, String> {
public String getKey( ent) {
return ent.getName();
}
}
public class BlessedHowDao extends BlessedDaoWager<BlessedEntity, Long> {}
public class BlessedNowDao extends BlessedDaoWager<BlessedEntity, Date> {}
}
There are those who say, what if someone inadvertently implemented the interface. I would say those are inadvertent programmers looking for ways to prevent their inadvertent programming habits.