I have a problem with the LSP in my program. I have a Base Class that is abstract and two different types of products , one is Food , the other is an Electronic device. I need to make a method that returns the expirationDate/Warranty for those products. The problem is that one is of type Date, and the other (warranty) is of type Int...
Do you have any idea how to make a method that satisfies both of those data types? without using switch/if statements since that will violate the OCP.
private static void printExpirationDateStatistics(List<Product> foodProducts) {
for (Product product : foodProducts) {
System.out.println(product.getExpirationDate());
}
}
Is there any way that is can modify this function to handle both food and electronics so I don't have to make another method for each new product is add ?
Those are the methods from the base class
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
public int getWarranty() {
return warranty;
}
public void setWarranty(int warranty) {
this.warranty = warranty;
}
I tried making one getValidity method but the problem is that for food it should return Date, and for electronics should return Int.
Any ideas ?
The problem you face here is that you want to abstract over two informationen a kind of common "expiration" information. The problem is that this abstraction is unknown to the code, it's currently only in present in your head :)
It's currently implemented in 2 flavours: Integers and Dates
(though I have no idea what this Integer is about? Is it a year count? ... the number of lottory winner since 1990? I don't know).
I would propose adding a new Interface for this abstraction, e.g.
public interface Expiration<T> {
T getExpiration();
}
In this case your two base classes can implement Expiration<Date> and Expiration<Integer> and you could base your validation logic on that. For example like:
public boolean isValid(Expiration<Date> potentialyExpired) {
final Date expirationDate = potentialyExpired.getExpiration();
final Date now = new Date();
return expirationDate.before(now);
}
That can only be done when you can access the classes in question though.
Is this abstraction enough or are you in need in even more?
You could want to abstract over the different type of Expiration in such a way that you don't need to have both of them around and unify them at some point. But to decide that kind of thing one would need to know more about the meaning of the other type (the Integer one).
Related
I have an algorithm, and I have 2 different implementations of the algorithm. These implementations should be called from many places, depending on the mode selected by the user. I wouldn't like to write conditional statements at all places where implementations called. So, I create an abstract class and Implementations inherit it. I can set the desired mode in one place like this:
if(firstMode){
list = new ListForm1();
}
else{
list = new LiastForm2();
}
And after that in all other places I can enjoy all the benefits of polymorphism.
It works good but I want to get rid of the inheritance of the following reasons:
I heard that composition is much better than inheritance.
The first form of the algorith is much easier then the second form. In the first form I have only 3 methods and in second form I have 15 methods. The abstract class had to include all 15 (and 5 common methods). It turns out that the 12 methods not using by the first form.
Theoretically, there may be a new form of the algorithm, which will have even less in common with the other two, but it will bring 10 new methods and all of them will have to add an abstract class.
The Strategy Pattern, as I understand, does not make sense to use here.
Here is the example of Strategy Pattern:
//abstract strategy
interface Strategy {
int execute(int a, int b);
}
// concrete strategy1
class ConcreteStrategyAdd implements Strategy {
public int execute(int a, int b) {
return a + b;
}
}
// concrete strategy2
class ConcreteStrategySubtract implements Strategy {
public int execute(int a, int b) {
return a - b;
}
}
//concrete strategy3
class ConcreteStrategyMultiply implements Strategy {
public int execute(int a, int b) {
return a * b;
}
}
class Context {
private Strategy strategy;
public Context() {
}
// Set new concrete strategy
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
// use strategy
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}
It has the same problems. Strategies should be linked with each other. If I link them with the interface instead of an abstract class it will be even worse. Interface will contain a lot of methods but many of them will not be needed for the first form of the algorithm. In addition, general methods have to duplicate in all concrete strategies. I can not provide a default implementation in the interface.
Moreever, I don't understand how to use composition here. As I understand, Strategy Pattern already used composition. Class Context includes the instance of Strategy as a field. But maybe it is delegation.
So, here is my question:
Can I get rid of all the above problems (too many methods of an abstract class, the strong connection, because of which it will be difficult to add a new form of an algorithm), but still use conditional statements in only one place, not in all cases when I need some form of algorithm.
UPD:
I want to show how I called some methods, which implemented in SECOND form of the algorithm, but not need for the FIRST form of algorithm:
if (list.getCurrentLeaders().contains(ballIdx))
The default implementation of method getCurrentLeaders() return null. So, if I called it with instance of the FIRST form of the algorithm then I will get an error. I understand that it is bad. But how can I solve it?
Starting from the beginning in the case you need to call a different algorithm based on a different mode chosen by the user you could create a kind of factory class to supply the algorithm throughout your code. I think that if it is only an algorithm and if you are on Java 8 you can use a Function or a Predicate or a Supplier in combination with a map to avoid the if statement, for example :
Map<String, Predicate<Whatever>> map = new HashMap<>();
map.put("mode_one", (w) -> true);
map.put("mode_two", (w) -> false);
Then to call the algorithm, simply :
map.get("mode_one").test()
In the case you need to supply a different form like in the example you posted, you could use a Supplier instead of a predicate.
Based on your simple requirement, I think that going functional would be the best bet ...
If you are not implementing all the methods (ie. if you have 15 methods in the abstract class to be implemented, and you only need to implement 10), then you are breaking the Liskov Substitution Principle :
https://en.wikipedia.org/wiki/Liskov_substitution_principle
Basically, that is a bad thing.
Try and convert the non-common methods into some other kind of object that gets passed into the constructor (on the abstract).
You can implement some kind of Chain Of Responsibility pattern.
interface IStrategy {
void Run();
bool CanHandle(IContext context);
}
class StrategyChecker {
IStrategy GetStrategy(IContext context) {
foreach(var strategy in strategies) {
if(strategy.CanHandle(context)
return strategy;
}
return defaultStrategy;
}
}
class Director {
void Run() {
strategyChecker.AddStrategy(strategy1);
strategyChecker.AddStrategy(strategy2);
var strategy = strategyChecker.GetStrategy(someContext);
strategy.Run();
}
}
Sorry for c# pseudo-code.
I heard that composition is much better than inheritance.
Not always - many times inheritance is the right construct. You have to think about it in has a and is a terms. A football team has a collection pf players. It also has a coach, a schedule, a name, etc. So Team : List<Player> is not the right construct.
A Car is a Vehicle, so inheritance is the right construct.
So think about your design this way:
Do my classes share a common base? Is there a base class that makes sense to say ListForm1 is a ListBase and ListForm2 is a ListBase. What methods and properties are common to those types that should be in the case type? What methods and properties should be virtual so that I can override them?
The first form of the algorithm is much easier then the second form. In the first form I have only 3 methods and in second form I have 15 methods. The abstract class had to include all 15 (and 5 common methods). It turns out that the 12 methods not using by the first form.
So maybe your base type only 3 methods, and you add methods in the sub-types as necessary. Remember that you can have multiple base types in the chain, but it's a chain, not a tree, meaning you can have a single parent that has another parent, but you can't have two parents.
Or maybe you have orthogonal interfaces since you can implement multiple interfaces.
Theoretically, there may be a new form of the algorithm, which will have even less in common with the other two, but it will bring 10 new methods and all of them will have to add an abstract class.
Why? Why can't the new algorithm just define its own methods that it needs, so long as clients pick the appropriate level in the inheritance chain (or appropriate interface(s)) so that it knows what methods should be implemented.
if (list.getCurrentLeaders().contains(ballIdx))
The default implementation of method getCurrentLeaders() return null. So, if I called it with instance of the FIRST form of the algorithm then I will get an error. I understand that it is bad. But how can I solve it?
So do you need to check that this particular list implements an interface (or inherits a base class) that does implement that method?
Why not just use your IStrategy as a type?
interface IStrategy {
int execute(int a, int b);
}
class Strategy1 implements IStrategy {}
class Strategy2 implements IStrategy {}
static class StrategyFactory {
IStrategy Create(bool first) {
return first ? new Strategy1() : new Strategy2();
}
}
And then in your user code:
void doStuff()
{
IStrategy myStrategy = StrategyFactory.Create(true);
myStrategy.execute(1, 2);
}
I'm currently working on a codebase where there are a few classes of variable, like database paths, which are simply represented as Strings. Most of the operations on these (non-)types are defined in a utility class.
I have created a new class to represent a database, with operations defined as instance methods, in traditional OOP style. However it is quite laborious to go through the large codebase and refactor it to use the new types. Does anyone have any advice as to how to do this quickly and effectively?
Migrate the utility class to use your new class. Then the utility class methods should only contain two statements. One for creating your class and the other is invoking your class. After that, you can inline the utility class methods thereby eliminating the need for it.
When you are finished with that, you need to look for a way to not instantiate your new class over and over again. This should be done by refactoring the local variable to an instance field which is initialized at construction time.
Database paths sound like they should be Strings to me. What else makes sense? And they should be externalized, either in configuration files or a database. That's the least of your problems.
Persistence has been so many times over (e.g. Hibernate, Spring JDBC, iBatis, etc.) that I'd wonder how you could possibly improve on them. If you have to go to the trouble of refactoring - and you must - I'd advise using anything other than what you've done.
If you must write something, Google for "generic DAO". You'll get stuff like this:
http://www.ibm.com/developerworks/java/library/j-genericdao/index.html
If your work isn't patterned after something like that, throw it away and re-think things.
A technique I've used in C# (and just ported to Java - apologies if I've made an error, I'm new to Java) is to create StringlyTyped classes, e.g. a base class
public abstract class StringlyTyped {
private String value;
public StringlyTyped (String value){
if (value == null){
throw new IllegalArgumentException("value must not be null");
}
this.value = value;
}
public String getValue() { return value; }
#Override
public boolean equals(Object other){
if (other == this) {
return true;
}
if (other == null || !this.getClass().equals(other.getClass())){
return false;
}
StringlyTyped o = (StringlyTyped)other;
return o.getValue().equals(this.getValue());
}
#Override
public int hashCode(){ return this.getValue().hashCode(); }
#Override
public String toString() { return this.getValue(); }
}
Then derived class
public class ProviderName extends StringlyTyped {
public ProviderName(String value) {
super(value);
}
}
And usage
public void Foo(ProviderName provider) {
}
It makes sense when you have methods with many String parametrers, e.g. you can avoid
public void Foo(String username, String password, String db, String table, String constraint)
and instead have code that is strongly typed like this:
public void Foo(UserName username, Password password, DatabasePath db, TableName table...)
etc...
I generally try to isolate the strings at the limit of the application/process boundary, such as when they are retrieved from a database or received via a web operation.
At that application/process boundary is often the ideal place to map/convert/deserialize the strings into a more proper object model, as supported by whatever language you are using.
Similarly, the object model can be mapped/converted/serialized back into string form as it exits your application/process boundary.
It is worth noting that this stringly typing can be somewhat subtle. I commonly see xml intruding into application and domain layers. A similar example from the .NET space would be failing to map ADO.NET DataTables (with their string column names and untyped field values) into classes/objects pretty much as soon as they are received. I have no doubt that there are many similar equivalents in the Java world. Stringly Typing is not just limited to date values, as the joke goes.
I have a custom object like this :
Linkedlist<ClassInfo> classes = new LinkedList<ClassInfo>();
Within that, there are accessors for a teacher's name, the class name, the room number, etc. These are all Strings. I have run into a situation where the data in that LinkedList needs to displayed by different parameters (i.e. teacher name, class name, the room number, etc.).
Can anyone supply a quick implementation of how to do this? If I use the Compartor interface, how would I be able tell it which String field to sort the list by? My research also lead me to the Collator, and I was wondering if this would be of use.
Appreciate any help.
Write a different Comparator implementation for each field:
Comparator<ClassInfo> CLASS_NAME_COMPARATOR = new Comparator<ClassInfo>() {
public int compare(ClassInfo class1, ClassInfo class2) {
return class1.getClassName().compareTo(class2.getClassName());
}
};
... // implementations for other fields
...and then sort by whichever comparator is appropriate:
Collections.sort(classes, CLASS_NAME_COMPARATOR);
You will have to provide a custom comparator for every ordering you need to sort your collection to. Eg:
class TeacherComparator implements Comparator<ClassInfo> {
public int compare(ClassInfo c1, ClassInfo c2) {
String teacher1 = c1.getTeacher();
String teacher2 = c2.getTeacher();
return teacher1.compareTo(teacher2);
}
}
class ClassNameComparator implements Comparator<ClassInfo> {
...
}
I have written a Java enum where the values have various attributes. These attributes could be stored in any of the following ways:
Using fields:
enum Eenum {
V1(p1),
V2(p2);
private final A attr;
public A attr() { return attr; }
private Eenum(A attr) {
this.attr = attr;
}
}
Using abstract methods:
enum Eenum {
V1 {
public A attr() { return p1; }
},
V2 {
public A attr() { return p2; }
}
public abstract A attr();
}
Using class level map:
enum Eenum {
V1,
V2;
public A attr() { return attrs.get(this); }
private static final Map<Eenum, A> attrs;
static {
ImmutableMap.Builder<Eenum, A> builder = ImmutableMap.builder();
builder.put(V1, p1);
builder.put(V2, p2);
attrs = builder.build();
}
}
How should I decide when to prefer which?
Thanks!
I would do the one which you think is the simplest.
In general I don't write code which can be implemented using data. I would use the first one.
My actual use case has some attributes which are not relevant for all enum values
You can use a combination of these approaches if it makes sense on a per attribute basis.
A fourth option is to not have an abstract method.
enum Eenum {
V1 {
public A attr() { return p1; }
},
V2 {
public A attr() { return p2; }
},
V3, V4, V5, V6;
public A attr() { return defaultA; }
}
None of those. Do this:
interface HasAttr<T> {
T attr();
}
enum Eenum implements HasAttr<A> {
// use "fields" version - ideally with constructor version
public A attr() {
return field;
}
}
This pattern follows the fundamental Abstract Type design pattern, which allows for method like:
public void someMethod(HasAttr<A> hasAttr); // pass anything that is HasAttr<a>
in preference to the fixed type:
public void someMethod(Eenum eenum); // locked into passing an Eenum
Also, and importantly, it's easier to mock for testing, especially if your enum uses real connections etc.
I grant you, all this only applied if the enum is "nontrivial". If it's just a plain old enum, I agree it's just code bloat (which I also detest)
(I am answering my own question so that I can share some things I learned while trying out things.)
Here are the questions you should ask to come at a decision for your specific case:
1: Do the attribute values involve forward references?
Sometimes V1's attribute may need a reference to V2 and vice versa. This is not a rare case. If you are dealing with such an enum, approach 1 simply would not work. The compiler will (rightly) complain about illegal forward references. Any of the other two approaches can be used.
Now, if the attribute value is expensive to compute and a constant, you'd want that it's computed only once. With approach 2, you'd have to introduce local variables per enum value, and cache results there. This is verbose but will give you better performance. With approach 3, the results are anyway computed only once, and so don't have to do any extra work. This is more readable but somewhat less performant than approach 2. Design between these as per the specific trade offs warranted in your case.
2: Do I need to cache results?
Refer to the second paragraph of previous bullet.
If there are no forward references, you can use approach 1 too. But if the computation involved in calculation of attributes is complex, you are better off with one of the other two approaches.
3: Are the attributes relevant for all of the enum values?
If not, then quite logically, you should be using a Map here. That is, approach 3.
4: Are there any default values for some attributes for some enum values?
If so, you can use all three approaches, and they all offer different set of trade-offs.
With approach 1: You would define an auxiliary constructor that initializes the attribute to the default value. If there are multiple such attributes, this might not be a feasible approach.
With approach 2: This will actually be like "fourth" approach Peter Lawrey suggested above. You will have a method returning the default value in enum's main body. And some enum values will override this method to return a different value. This is, again, quite verbose.
With approach 3: Just less efficient. Good in every other way.
I am writing a program to simulate cities from a game called Civilization 4. In order to do this I have several Enums to represent types of terrain, resources, improvements etc for each plot owned by said city.
The problem is I want to program to be compatible with Fan made mods which may add things to the Game that need to be accepted into my independant utility. So I thought of creating a Enum style class to hold the new types defined by the loaded mods (as Enums cannot be changed at runtime) which is created during runtime when the user enters in a mod to be loaded (which is a txt file that is parsed to read the new additions)
So is there a way to simulate Enums that are created and added to at runtime? I take it static member variables cannot be used as they are done before runtime...
You can make a enum implement an interface.
This way you can have your defined values in the enum, but new values can be any class which implements the interface.
An alternative is that you generate or load the enum at runtime using a byte code generator or the Compiler API. I wrote a library to make it easier to take a String and compile&load it.
http://vanillajava.blogspot.co.uk/2010_11_01_archive.html
Well, enums in Java are simply classes where the language guarantees that the set of known objects is known and limited at compile-time. If you want to add new enum literals at runtime, you end up with regular classes.
The beauty of enums is that you can write human readable names in code that are compiled as numbers behind the scenes, because computers like numbers better. Take for example this enum:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Behind the scenes WINTER might be 0 (zero), SPRING is 1 etc.
To replicate this behaviour in runtime code you could create a list of strings, like this:
List<String> seasons;
seasons = new ArrayList<String>();
seasons.add("Winter");
seasons.add("Spring");
...
That way you can reference the items as numbers, such as seasons[1] would equal "Spring".
This answer is just one of many ways to approach this question.
By default, enum types have only a set number of values. The values in an enum type are actually declared as static final, and there's no way to add more on runtime.
That being said, there are other patterns you can use to implement what you want. Let's take a look at using an interface and a registration system. We'll start with the Terrain interface:
public interface Terrain {
int getId();
String getName();
int getSightBonus();
}
Now an enum, DefaultTerrain:
public enum DefaultTerrain implements Terrain {
PLAINS(0, "Plains", 1),
HILLS(1, "Hills", -1),
MOUNTAINS(2, "Mountains", -2);
private int id;
private String name;
private int sightBonus;
private DefaultTerrain(int id, String name, int sightBonus) {
this.id = id;
this.name = name;
this.sightBonus = sightBonus;
}
public int getId() {return id;}
public String getName() {return name;}
public int getSightBonus() {return sightBonus;}
}
And a registration class, which can be either a static utility class or a singleton.
public class TerrainManager {
private static Map<Integer, Terrain> terrainsById = new HashMap<>();
static {
for (DefaultTerrain terrain : DefaultTerrain.values())
register(terrain);
}
public static void register(Terrain terrain) {
Integer id = terrain.getId();
if (terrainsById.contains(terrain.getId()))
throw new IllegalArgumentException("Terrain with id already exists: " + id);
terrainsById.put(id, terrain);
}
public static Terrain getTerrainById(int id) {
return terrainsById.get(id);
}
public static Set<Terrain> getAllTerrains() {
return new HashSet<Terrain>(terrainsById.values());
}
}
This last class is where the magic happens. Presumably the modders will have some kind of identifier in the game's world definition to say "use this tile," right? In this case, I've called it an integer, id, but really it could be any type, just modify the Map accordingly. In the map-loading code, just use the ID in the world definition to look up the Terrain. When a modder adds a new Terrain, they just need to implement Terrain and register it with TerrainManager.
The static initializer makes sure that your DefaultTerrain objects are added before anything else is added. If you use a singleton, this could be put into the class constructor instead.
Use this pattern for your different enum types that you want users to add to. You could also use it for pretty much any other type as well besides enum.
You will need CGLIB, http://cglib.sourceforge.net/