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.
Related
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);
I have two classes that extend an abstract class in a very similar manner, and I'd like to abstract out the common parts since I will likely have to use this again. They each return a ThingLink containing data linking them to a Parent object. They also return a Widget that varies based on the class, but only up to their name. Here is the pattern:
public abstract class SomeClass extends TopClass {
protected abstract Widget createWidget();
public void someMethod() { // Does something }
}
public class ThingA extends SomeClass {
private static final String INFO_TYPE = "int";
public ThingLink newLink(Parent master, Int info) {
ThingLink link = new ThingLink(parent, ThingA.class);
link.addData(INFO_TYPE, info);
return link;
}
public Widget createWidget() {
// Stuff to get someData
return ThingAWidget.createMe(someData);
}
}
public class ThingB extends SomeClass {
private static final String INFO_TYPE = "String";
public ThingLink newLink(Parent master, String info) {
ThingLink link = new ThingLink(parent, ThingB.class);
link.addData(INFO_TYPE, info);
return link;
}
public Widget createWidget() {
// Stuff to get someData
return ThingBWidget.createMe(someData);
}
}
I have no access to TopClass, the ThingLink class, or the Widget class. I was trying to abstract out the common parts using generics, but I can't seem to figure out if that will provide a complete solution. My big problem is figuring out how to get the pieces that are self-referential. I would like a class something like:
public abstract class Thing<T> extends SomeClass {
private String infoType;
public void setInfoType(String type) { infoType = type; }
public ThingLink newLink(Parent master, T info {
ThingLink link = new ThingLink(parent, ???????????);
link.addData(infoType, info);
return link;
}
public Widget createWidget() {
// Stuff to get someData
return ??????????????.createMe(someData);
}
}
Keep in mind that I am fairly new to Java, and self-taught, but I am trying very hard to make some bigger leaps and really understand how to write good code. I appreciate your help.
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. ;-)
I am trying to create an MXBean with a custom attribute, but I get javax.management.NotCompliantMBeanException
IJmsDestinationMBean.getAttributes has parameter or return type that cannot be translated into an open type
I have read that MXBean attributes have to be OpenType compatible.
How would I make my attribute work this way?
All the classes below are in the same package.
class JmsDestinationMBean implements IJmsDestinationMBean{
protected JmsDestinationAttributes attributes = new JmsDestinationAttributes();
#Override
public JmsDestinationAttributes getAttributes() {
return this.attributes;
}
}
#MXBean
interface IJmsDestinationMBean {
JmsDestinationAttributes getAttributes()
}
class JmsDestinationAttributes {
protected String name
protected int messagesCurrentCount
protected int consumersCurrentCount
String getName() {
this.name;
}
int getMessagesCurrentCount() {
this.messagesCurrentCount;
}
int getConsumersCurrentCount() {
this.consumersCurrentCount;
}
}
The problem is the interface IJmsDestinationMBean. It returns a type JmsDestinationAttributes which is not an open type. Here's the rules-of-thumb I follow when doing this:
The actual registered MBean (which has a complex typed attribute) is called Foo and it's management interface is called FooMXBean.
The complex type (the attribute of Foo is called Bar and has a management interface called BarMBean. This guy cannot return any values that are not open types or other properly exposed complex types.
So (for this example) the "host" MBean needs to be an MXBean in order to support complex types , and the complex type needs to have an interface called <ClassName>MBean. Note that one has the MXBean interface, and the other has the MBean interface.
Here's my example:
JMSDestination implements JMSDestinationMXBean
JmsDestinationAttributes implements JmsDestinationAttributesMBean
...apologies for the loose case standard. It's an on the fly example.
Here the JMSDestination code, with a main to create and register. I am simply using the user name property to provide the name.:
public class JmsDestination implements JmsDestinationMXBean {
protected JmsDestinationAttributes attrs = new JmsDestinationAttributes(System.getProperty("user.name"));
public JmsDestinationAttributes getAttributes() {
return attrs;
}
public static void main(String[] args) {
JmsDestination impl = new JmsDestination();
try {
ManagementFactory.getPlatformMBeanServer().registerMBean(impl, new ObjectName("org.jms.impl.test:name=" + impl.attrs.getName()));
Thread.currentThread().join();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
}
The JMSDestinationMXBean code:
public interface JmsDestinationMXBean {
public JmsDestinationAttributes getAttributes();
}
The JmsDestinationAttributes code which uses the same name and random numbers for the values:
public class JmsDestinationAttributes implements JmsDestinationAttributesMBean {
protected final String name;
protected final Random random = new Random(System.currentTimeMillis());
public JmsDestinationAttributes(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getMessagesCurrentCount() {
return Math.abs(random.nextInt(100));
}
public int getConsumersCurrentCount() {
return Math.abs(random.nextInt(10));
}
}
.... and the JmsDestinationAttributesMBean:
public interface JmsDestinationAttributesMBean {
public String getName();
public int getMessagesCurrentCount();
public int getConsumersCurrentCount();
}
The JConsole view looks like this:
The JConsole view of the MXBean's attributes looks like this:
Make sense ?
As the title presumes, how do I this in Java? What im trying to do is something like this
first there is a class
public class MyFirstModel() {
//standard constructor
public MyFirstModel(){
//some lines of codes
}
//A method
public String getvalue() {
//do something then
return result;
}
}
And the second Model(class)
public class MySecondModel() {
//standard constructor
public MySecondModel(){
//some lines of codes
}
//A method
public String getvalue() {
//do something then
return result;
}
}
Having those two, sample, models i want to pass a class depending on the, action. Let's just say there are two buttons and the first button is for the model and the second is for the second model. The third class that is to be pass to:
FinalClass fclass = new FinalClass(<class here>); <-- how do i pass the class here
Here, how do I pass the class? on the FinalClass, what would be its constructor? and how do I acces the methods of the passed class?
I hope you guys get what I mean. Please help.
You don't want to have both models implement an interface?
MyModel.java:
public interface MyModel {
public String getValue();
}
MyFirstModel.java:
public class MyFirstModel implements MyModel {
public String getValue() {
// stuff
}
}
MySecondModel.java:
public class MySecondModel implements MyModel {
public String getValue() {
// stuff
}
}
CallingClass.java:
public class CallingClass {
private MyModel model = null;
public CallingClass(MyModel model) {
this.model = model;
}
}
Then you can construct MyModel however you want and pass it in to CallingClass.
You can create an Anonymous Object by using an interface:
public interface FinalClass {
// Method definitions
}
public class MyFirstModel() implements FinalClass {
//...
}
public class MySecondModel() implements FinalClass {
//...
}
Use:
FinalClass fclass = new MyFirstModel();
// or
FinalClass fclass = new MySecondModel();