I have following structure.
DynamoDBDao{
public get(String hashKey,String rangeKey){
//validation rule
}
}
T1DynamoDBDao extends DynamoDBDao{
public get(String name,String surname){
// same validation rule
super.get(name,surname);
}
}
Does it make sense to duplicate validation rule in T1DynamoDBDao?
No, not only do you potentially validate the input multiple times, you also violate the DRY principle.
One option is to have a private or protected member that does the actual work after the parameters have been validated:
class Base {
public final Object get( String arg )
{
if( !validate( arg ) )
{
//throw?
}
return get_validated( arg );
}
protected Object get_validated( String arg )
{
// do work
}
}
public class Derived extends Base
{
protected Object get_validated( String arg )
{
// do work
// maybe super.get_validated( arg );
}
}
Because T1DynamoDBDao is a sublcass of DynamoDBDao, it can access all public methods from the supercalss. Personally, I wouldn't duplicate it.
Related
I'm trying to have an enum correspond to a class or return that class but I get to resolve. Is this behavior possible if I use the CommandType.SELLSHARES for it to return SellShares.class? Or can I organize the enums with different categories that inherit from the parent type?
Commands - ADMIN, USER, CLIENT
public enum CommandType {
// SELLSHARES, BUYSHARES, UPDATEUSER, ADDUSER, ADMINASSIGNMENT, BANUSER, CHANGESTATUS, REMOVEUSER
SELLSHARES (SellShares.class),
BUYSHARES (BuyShares.class);
private Class<Command> command;
CommandType(Class<Command> command) {
this.command = command;
}
private Class<Command> command() { return command; }
public static <T extends Enum<T>> T getInstance(final String value,
final Class<T> enumClass) {
return Enum.valueOf(enumClass, value);
}
}
OR
public enum CommandType {
AdminCommands,
UserCommands
}
enum AdminCommands {
UPDATEUSER,
ADDUSER,
ADMINASSIGNMENT,
BANUSER,
CHANGESTATUS,
REMOVEUSER
}
enum User {
SELLSHARES,
BUYSHARES
}
Having problem with getByType
void initialCommands() throws Exception
{
listCommands = Commands.getByType(Commands.Type.ADMIN);
for (Commands command : listCommands)
{
Command commandss = command.newInstance();
//addCommand(command.getCommand());
//log.trace(command.newInstance());
}
}
You must be looking for something like this:
public enum Commands {
UPDATE_USER(Type.ADMIN, UpdateUser.class),
ADD_USER(Type.ADMIN, AddUser.class),
ADMIN_ASSIGNMENT(Type.ADMIN, AdminAssignment.class),
BAN_USER(Type.ADMIN, BanUser.class),
CHANGE_STATUS(Type.ADMIN, ChangeStatus.class),
REMOVE_USER(Type.ADMIN, RemoveUser.class),
SELL_SHARES(Type.USER, SellShares.class),
BUY_SHARES(Type.USER, BuyShares.class);
public enum Type {
ADMIN,
USER;
}
public static List<Commands> getByType(Type type) {
List<Commands> commands = new ArrayList<Commands>();
for (Commands command : values()) {
if (command.type.equals(type)) {
commands.add(command);
}
}
return commands;
}
private final Type type;
private final Class<? extends Command> command;
private Commands(Type type, Class<? extends Command> command) {
this.type = type;
this.command = command;
}
public Class<? extends Command> getCommand() {
return command;
}
public Command newInstance() throws Exception {
return command.newInstance();
}
}
To create an instance, simply use:
Commands.UPDATE_USER.newInstance();
To get all the commands for a given type:
Commands.getByType(Commands.Type.ADMIN);
Note that using this method, the Commands subclasses must implement a public nullary constructor.
I wish to offer this advice and pattern.
Do not ever use for/while/loops on an enum.
Reduce use of if-then-else on an enum.
But exploit the fact that an enum is an efficient hashmap. Build actions into the enum so that you don't have to iterate on the enum to resolve actions due to an enum.
Avoid using if blocks to resolve the appropriate action for an enum, but build the function lambda into the enum.
Design your code to use EnumSet as much as possible to "sub class" your enum.
Redesign the flow of your code to make use of EnumSet.
Don't use the plural but Command as the enum class name. So that you'd reference a command holder as Command.ADDUSER rather than Commands.ADDUSER.
Example of using EnumSet to categorize items in the enum,
enum Command {
UPDATEUSER,
ADDUSER,
ADMINASSIGNMENT,
BANUSER,
CHANGESTATUS,
REMOVEUSER,
SELLSHARES,
BUYSHARES,
;
final static public EnumSet<AdminCommands> ADMIN = EnumSet.of(
UPDATEUSER,
ADDUSER,
ADMINASSIGNMENT,
BANUSER,
CHANGESTATUS,
REMOVEUSER
);
final static public EnumSet<AdminCommands> USER= EnumSet.of(
SELLSHARES,
BUYSHARES
);
}
Building the class constructor call, and their respective actions into the enum:
interface Commander{}
#FunctionalInterface
public interface CommanderNoArg extends Commander {
Action getAction();
}
#FunctionalInterface
public interface Commander1Arg extends Commander {
Action getAction(ActionContext ctx);
}
#FunctionalInterface
public interface Commander2Arg extends Commander {
Action getAction(ActionContext ctx, Options opts);
}
// Auxiliary casters needed due to Java's silly deficient treatment of generics
static private CommanderNoArg hasNoArg(CommanderNoArg lambd) {
return lambd;
}
static private Commander1Arg has1Arg(Commander1Arg lambd) {
return lambd;
}
static private Commander2Arg has2Args(Commander2Arg lambd) {
return lambd;
}
enum Command {
UPDATEUSER(hasNoArg(UserContext::new) ),
ADDUSER(hasNoArg(UserContext::new) ),
ADMINASSIGNMENT(has1Arg(AdminContext::new) ),
BANUSER(hasNoArg(UserContext::new) ),
CHANGESTATUS(hasNoNoArg(UserContext::new) ),
REMOVEUSER(hasNoNoArg(UserContext::new) ),
SELLSHARES(has2Args(UserContext::new) ),
BUYSHARES(has2Args(UserContext::new) ),
;
final public Commander commander;
private Command(Commander cmdr) {
this.commander = cmdr;
}
}
Where because
UserContext has constructor that requires no argument
UserContext also has constructor that requires 2 arguments
AdminContext has constructor that requires 1 argument.
You would get the Action class by, e.g.,
// AdminContext requires 1 argument
Assignment assg = getAssgFromSomewhere();
Action act =
((Commander1Arg )Command.ADMINASSIGNMENT.commander)
.getAction(assg);
Or perhaps, you could feed in lambdas of static methods into the enum items rather than a class.
First of all, sorry for the bad title. I don't know how to describe the problem in a few words (maybe not even in many)...
I am refactoring some settings in our system to be more abstract. The current solution has multiple tables in the DB, one for each settings area. In order to add a new setting, you'll need to extend the schema, the hibernate class, all transfer object classes, getters/setters, etc. I felt that this is violating OCP (open-closed principle), thus the refactoring.
I've spent some time coming up with ideas on how to implement such an abstraction. My favourite idea so far is the following:
1 enum for each settings area
1 enum value for each setting
Each setting is a SettingsDefinition<T> class using a generic type
A SettingsService is using static get/set methods with generic types
So for example, a settings area could be:
public enum SettingsABC{
A(new SettingDefinition<Integer>("A", 123)),
B(new SettingDefinition<String>("B", "Hello")),
C(new SettingDefinition<Boolean>("C", false));
private SettingDefinition settingDefinition;
SettingsABC(SettingDefinition settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition getDefinition() {
return settingDefinition;
}
}
Where the SettingDefinition is the following:
public class SettingDefinition<T> {
private String name;
private T defaultValue;
public SettingDefinition(String name, T defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public T getDefaultValue() {
return defaultValue;
}
}
And the service to get/set the values would be:
public class SettingsService {
public static <T> T getSetting(SettingDefinition setting) {
// hit db to read
// return value
}
public static <T> void setSetting(SettingDefinition setting, T value) {
// hit db to write
}
}
And the consumer would look something like this:
String value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), 123);
My problem is that I cannot enforce a compiler type check between the generic type of the SettingDefinition inside SettingsABC and the generic type of get/set methods of the service. So in essence, I can do this:
Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
Where B's definition is of type String.
Also, I can do this:
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
Where A's definition is an Integer.
Is there any way to use generics to force these two different generic types match?
You can convert the enum to the class:
public final class SettingsABC<T> {
public static final SettingsABC<Integer> A =
new SettingsABC<>(new SettingDefinition<>("A", 123));
public static final SettingsABC<String> B =
new SettingsABC<>(new SettingDefinition<>("B", "Hello"));
public static final SettingsABC<Boolean> C =
new SettingsABC<>(new SettingDefinition<>("C", false));
private final SettingDefinition<T> settingDefinition;
// private constructor, so nobody else would instantiate it
private SettingsABC(SettingDefinition<T> settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition<T> getDefinition() {
return settingDefinition;
}
}
This way individual constants will be typed. Now you can use the type arguments for SettingService as well:
public static <T> T getSetting(SettingDefinition<T> setting) {
...
}
public static <T> void setSetting(SettingDefinition<T> setting, T value) {
...
}
Although it's not an enum anymore, it can be used mostly in the same way. If you need other methods which are usually available in enum, you can mimic them like this:
public String name() {
return settingDefinition.getName();
}
#Override
public String toString() {
return settingDefinition.getName();
}
// and so on
I have imported an API which includes an Enumeration. Now in a different class, I need to invoke a method which takes Enumeration as argument.
getValueDateByTenorType(Enumeration tenure)
But I have no idea how can I pass Enumeration as we cannot instantiate an Enumeration.
If the enum is in the same class you can pass the enum as shown below.
public class CollegeTenure{
public enum TENURE{
HALF_YEARLY, FULL_PROFESSORSHIP;
}
public void getValueDateByTenorType(TENURE tenure){
if( TENURE.HALF_YEARLY.equals( tenure ) ) {
System.out.println("Half Yearly tenure");
} else if( TENURE.FULL_PROFESSORSHIP.equals( tenure ) ) {
System.out.println("Full Professorship tenure");
}
}
public static void main(String[]args) {
CollegeTenure collegeTenure = new CollegeTenure();
collegeTenure.getValueDateByTenorType(TENURE.HALF_YEARLY);
}
}
enum can also be defined in another class as public
public class Constants{
public enum TENURE{
HALF_YEARLY, FULL_PROFESSORSHIP;
}
}
public class CollegeTenure2{
public void getValueDateByTenorType(Constants.TENURE tenure){
if( Constants.TENURE.HALF_YEARLY.equals( tenure ) ) {
System.out.println("Half Yearly tenure");
} else if( Constants.TENURE.FULL_PROFESSORSHIP.equals( tenure ) ) {
System.out.println("Full Professorship tenure");
}
}
public static void main(String[]args) {
CollegeTenure2 collegeTenure2 = new CollegeTenure2();
CollegeTenure2.getValueDateByTenorType(Constants.TENURE.FULL_PROFESSORSHIP);
}
}
It depends on what you want to do with that Enumeration/Function, (provide more information for a more detailed answer) but most generally speaking, you have either to use any existing class that implements the Enumeration interface, (e.g. Collections.enumeration(myList)) or you have to build one on your own. This would be done as follows:
// User defined type specific Enumeration
// implements java.util.Enumeration Interface
class MyEnumeration<T> implements Enumeration<T>
{
#Override
public boolean hasMoreElements()
{
// provide boolean function to check if your Enumeration
// has more elements
return false;
}
#Override
public T nextElement()
{
// provide function that returns the next element
return null;
}
}
This class can then be passed to your API function (yet, you still have to know what is done inside this function to know what your Enumeration should contain):
getValueDateByTenorType(new MyEnumeration<String>());
You can add as many functions as you want to create or modify your Enumeration class, but you have to provide the two interface methods hasMoreElements and nextElement. For more information, review the documentation about Enumerations
and Interfaces.
Let's say I have a Strategy interface :
public interface Strategy {
void perform();
}
And a template method to implement it :
public abstract class AbstractStrategy implements Strategy {
#Override
public void perform() {
String firstInfo = doStuff();
String secondInfo = firstDelegationToImplementor(firstInfo);
String thirdInfo = processSecondInfo(secondInfo);
String fourthInfo = secondDelegationToImplementor(thirdInfo);
finalProcessing(fourthInfo);
}
private void finalProcessing(String fourthInfo) {
//TODO automatically generated method body, provide implementation.
}
protected abstract String secondDelegationToImplementor(String thirdInfo);
protected abstract String firstDelegationToImplementor(String firstInfo);
private String processSecondInfo(String secondInfo) {
return "thirdResult";
}
private String doStuff() {
return "firstResult";
}
}
And I have a concrete subclass of that :
public class ConcreteStrategy extends AbstractStrategy {
private String firstInfo;
#Override
protected String secondDelegationToImplementor(String thirdInfo) {
return someMoreProcessing(firstInfo, thirdInfo);
}
private String someMoreProcessing(String firstInfo, String thirdInfo) {
return null;
}
private String someProcessing(String firstInfo) {
return null;
}
#Override
protected String firstDelegationToImplementor(String firstInfo) {
this.firstInfo = firstInfo;
return someProcessing(firstInfo);
}
}
But due to the fact that it needs to remember some intermediate result in between the method calls it is not stateless. Stateless classes have several advantages, they are automatically thread safe for instance.
So the question is : how can I make ConcreteStrategy stateless, while taking advantage of the template method?
(edit) Clarification : the published methods of both the interface and the template method class cannot change.
(note, I have solved this question already and will answer it myself, but I'll give others a chance to solve it)
Ok here's the answer I have come up with when I faced this :
public class StatelessConcreteStrategy implements Strategy {
#Override
public void perform() {
new ConcreteStrategy().perform();
}
}
StatelessConcreteStrategy is stateless. It has all the benefits any other stateless class has, and by delegating the perform() to a new ConcreteStrategy instance, it gets to use the template method pattern, and is able to 'remember' any data it wants to in between method calls.
In fact you'll most likely want to inline ConcreteStrategy to an inner or even anonymous inner class.
public class Atribut {
int classid;
#Override public String toString() {
return Integer.toString(classid);
}
}
I have made this class which overrides method toString(). I plan on making many subclasses with different classid. The problem is I dont know how to set the variable classid to work in toString method.
public class cas extends Atribut{
int classid=2;
}
The problem is if I make an cas object and toString method it returns "0" not "2".??
My preferred technique for this kind of thing is to use constructor arguments:
public class Parent {
// Using "protected final" so child classes can read, but not change it
// Adjust as needed if that's not what you intended
protected final int classid;
// Protected constructor: must be called by subclasses
protected Parent(int classid) {
this.classid = classid;
}
#Override
public String toString() {
return Integer.toString(classid);
}
}
public class Child extends Parent {
public Child() {
// The compiler will enforce that the child class MUST provide this value
super(2);
}
}
Much as #java_mouse recommended, just use the parent class's variable.
public class Atribut {
protected int classid;
public Atribut() {
classid = 0;
}
#Override
public String toString() {
return Integer.toString(classid);
}
}
public class Cas extends Atribut{
public Cas() {
classid = 2;
}
}
Set classid's value in the constructor and then you can use the superclass's toString() just fine.
When you shadow the variable, the one in the parent class is used in methods there.
If you want to do this, I would do this
class Atribut {
int classid = 0;
protected int classid() { return classid; } // points to Attribut.classid
public String toString() {
return Integer.toString(classid());
}
}
Then in your child class, you can override the method
class cas {
int classid = 2;
protected int classid() { return classid; } // points to cas.classid
}
Why do you want to shadow a variable in child class if it is already available in the parent? why not using the same variable?
if you use the same variable, the issue is resolved automatically. Don't duplicate the attribute if it has to be inherited.
I think most of the answers here narrow down to style preference.
For such small examples, most of the provided solutions would work just fine.
However, let's assume that you have an inheritance tree that is several levels deep. In such a scenario, it might be challenging to understand the source of each property, so using setters, getters, and references to the superclass might come in handy. My personal choice would be as follows:
public class Atribut {
private int firstProp;
private int thirdProp;
public int getFirstProp() {
return firstProp;
}
public void setFirstProp(int firstProp) {
this.firstProp = firstProp;
}
....
#Override
public String toString() {
return Integer.toString(this.getFirstProp()) +
Integer.toString(this.getThirdProp());
}
}
public class Cas extends Atribut {
private int secondProp;
public Cas() {
super.setFirstProp(1);
this.setSecondProp(2);
super.setThirdProp(3);
}
}
An alternative implementation, using the approaches provided above would result in the this Cas class:
public Cas() {
super(1, 3)
secondProp = 2;
}
This second solution is a bit harder to read and is less descriptive about what properties are you setting.
For those reasons, that is the style that I prefer. Also, to reiterate, the benefits of the first approach become more evident for more complex examples.