I wonder if my aproach into modelling difficulty level for my game is good.
public abstract class AbstractDifficulty {
public AbstractDifficulty() {
}
public abstract int enemyWaves();
public abstract int enemiesInWave();
public abstract long enemyWaveIntervalMilis();
}
And then several subclasses which implement those methods, for example.
public class EasyDifficulty extends AbstractDifficulty {
#Override
public int enemyWaves() {
return 1;
}
#Override
public int enemiesInWave() {
return 10;
}
#Override
public long enemyWaveIntervalMilis() {
return 500;
}
}
I wonder if there is a simpler way to do this, but the same easy and clean to use as this.
Edit: Could someone be so kind to explain to me why this question got minus votes. Is something wrong with this code, or my explanation ? Thanks.
Your design will do the job, but it seems what you want to have is a container class. So instead having a method for each value, have a (final) field with the value and a getter. They can be set e.g. in the constructor.
If your difficulty modes are known and few, consider having an enum, which are final and easier to use.
enum Difficulty {
EASY(1, 10, 5000),
MEDIUM(2, 15, 4000),
HARD(4, 20, 3500);
private final int enemyWaves;
private final int enemiesInWave;
private final long enemyWaveIntervalMilis;
Difficulty(int enemyWaves, int enemiesInWave, long enemyWaveIntervalMilis ){
this.enemyWaves = enemyWaves;
this.enemiesInWave = enemiesInWave;
this.enemyWaveIntervalMilis = enemyWaveIntervalMilis;
}
public int getEnemyWaves() {
return enemyWaves;
}
public int getEnemiesInWave() {
return enemiesInWave;
}
public long getEnemyWaveIntervalMilis() {
return enemyWaveIntervalMilis;
}
}
One alternative is to not have different difficulty classes, but just one difficulty class with different instances being the different difficulties (so, a class with attributes enemyWaves, enemiesInWave and enemyWaveIntervalMilis, and different instances with different settings).
Your solution looks fine. If you want to increase readability you can just remove the constructor from the abstract class, since that is created by Java as default anyway.
I also vote for an interface instead of an abstract class unless there is a specific reason to use abstract class.
I also feel that for the specific problem you do not need different classes, but rather different instances of the same class. In that case I would use the final fields set by constructor and then the methods return the values.
public class Difficulty {
final private int enemyWaves;
public Difficulty(final enemyWaves){ this.enemyWaves = enemyWaves; }
#Override
public int enemyWaves() {
return this.enemyWaves;
}
}
Related
I have this classes:
package util;
public final class Constant {
private Constant() {
throw new AssertionError();
}
public static class Product {
public static final String CODE = "Product";
public static final String A = "product_5g2g";
public static final String B = "product_a45h";
public static final String C = "product_a3ag";
//more constants..
}
public static class Employee {
public static final String CODE = "Employee";
public static final String A = "employee_1g3f";
public static final String B = "employee_h52d";
public static final String C = "employee_h5d2";
//more constants..
}
public static class Client {
public static final String CODE = "Client";
public static final String A = "client_h5ad";
public static final String B = "client_1df1";
public static final String C = "client_6g23";
//more constants..
}
}
and:
package util;
import util.Constant.*;
public class Main {
public void run() {
if (isSelected(Product.CODE)) {
if (isSelected(Product.A) || isSelected(Product.B)) {
//do something
}
compute(Product.C);
//more similar instruction that use constants from Product class
}
if (isSelected(Employee.CODE)) {
if (isSelected(Employee.A) || isSelected(Employee.B)) {
//do something
}
compute(Employee.C);
//more similar instruction that use constants from Employee class
}
if (isSelected(Client.CODE)) {
if (isSelected(Client.A) || isSelected(Client.B)) {
//do something
}
compute(Client.C);
//more similar instruction that use constants from Client class
}
}
public boolean isSelected(String s) {
return true;
}
public void compute(String s) {
}
}
As you can see, this block of code
if (isSelected(StaticClass.CODE)) {
if (isSelected(StaticClass.A) || isSelected(StaticClass.B)) {
//do something
}
compute(StaticClass.C);
//more similar instruction that use constants from Product class
}
is repetitive, but can't put it in a separate method because java don't permit a static class as a parameter public void method(StaticClass) {}.
How can I refactor the above code? My first thought was to make Singletons that extend a base class, or implement an common interface. There is a better solution?
You should look into using polymorphism here. Example: instead of doing
if (X) {
doY();
}
"good" OO looks much more like:
Y y = getMeSomeY();
y.doTheY();
Where getMeSomeY() returns you exactly that what is required (so Y could be an interface; and that method provides different implementations of that interface which all do slightly different things).
The point is: you wrote procedural code, where you ask something, to then make a decision about it. Good OO favors the opposite (called tell don't ask).
You start by ... not making everything flat strings. By doing so, you give up on the whole "static typing" thing. If your code is making decisions only on strings, why are you programming in Java? You can very well use a non-typed language than. So, at least learn about Java enums; and use those. But please understand: enums are not the real answer here. They would just help to make your code a bit better.
The real problem here is that you want to write code doing these if (x) then y all over the place.
You might have guessed by now: there is no easy answer here. What I would do: first, step back. And have a in-depth look into your design. The code you have right now indicates to me that your underlying object model is far from "helpful". And that is the whole point of OO: you create classes and objects that help you to write clean, elegant code. But when your base design isn't supporting that; then there is no point in trying to refactor the code that came out of that. Because the ugliness of your code is just a symptom; the root cause lies in your design underneath.
What you are looking for is an Enum. Redefine all your classes as Enums instead. For example, you can redfine the Product class as follows :
public enum Product {
CODE("Product"),
A("product_5g2g");
private String value;
//define others constants in a similar fasion
public Product(String value) {
this.value = value;
}
}
Enums can be passed as method parameters. In your particular example, you can do this :
public void method(Constants.Product product) {
}
That said, you should definitely look into an alternative way to achieve your objective. Take a look at Replacing conditionals with Polymorphism for starters.
I am currently in the process of refactoring the code I wrote for a text/console version of the Mastermind board game. I am a bit stuck with how to best approach improving this section my GameLogic class.
public GameLogic(GameSettings gameSettings)
{
// ..other stuff..
// initialise static members
Board.setTotalRows(gameSettings.getNumOfGuesses());
Board.setTotalColums(gameSettings.getCodeLength());
// InputBoard and OutputBoard extends the abstract class Board
inputBoard = new InputBoard();
outputBoard = new OutputBoard();
}
What I am trying to do is set the static values of totalRows and totalColumns in the Board class BEFORE constructing the inputBoard and outputBoard objects. The reason why I want to do this is because I need to have these values present when constructing instances extending Board (an abstract class). The reason why I am making these values static is because they should be the same across all instances extending from Board and so that I can do something like Board.getTotalColumns() throughout the application.
The reason why I think this is suspiciously bad is because it would be possible to declare inputBoard or outputBoard without first setting the static member variables and of course it would also be possible to accidentally set the values of the static member later on to any arbitrary value.
Another approach I thought of was to make the getters in GameSettings public and static so that I could do something like this instead:
public abstract class Board
{
private static final int totalColumns = GameSettings.getCodeLength();
private static final int totalRows = GameSettings.getNumOfGuesses();
// other stuff...
}
This would allow me to avoid using setters and the problems associated with using them as listed above. But wouldn't this defeat the purpose of instantiating a GameSettings object?
What do you think are better alternatives to approach this?
I am not an expert on design pattern. I would try something like below -
Board.java
abstract class Board {
private final GameSettings gameSettings;
Board(GameSettings gameSettings) {
this.gameSettings = gameSettings;
}
public int getTotalColumns() {
return gameSettings.getCodeLength();
}
public int getTotalRows() {
return gameSettings.getNumOfGuesses();
}
//Other abstract methods
}
InputBoards .java
class InputBoards extends Board {
InputBoards(GameSettings gameSettings) {
super(gameSettings);
}
}
OutputBoards .java
class OutputBoards extends Board {
OutputBoards(GameSettings gameSettings) {
super(gameSettings);
}
}
GameSettings .java
class GameSettings {
public int getCodeLength() {
//return your value;
}
public int getNumOfGuesses() {
//return your value;
}
}
Now I would do -
public GameLogic(GameSettings gameSettings) {
inputBoard = new InputBoard(gameSettings);
outputBoard = new OutputBoard(gameSettings);
}
I have a class Player which contains few private fields of other classes ( I believe it is called composition ).
public class Player
{
private String name;
private Statistics statistics;
private Experience experience;
private Effort effort;
}
I will post only one of them called Statistics
public final class Statistics
{
Pool pool;
Edge edge;
class Pool
{
private Map<Stats, LimitedInt> map = new HashMap<>();
private int freePoints = 0;
void setAvailable(Stats stat, int value){}
int getAvailable(Stats stat){ return 0; }
void setMax(Stats stat, int value){}
int getMax(Stats stat, int value){ return 0; }
void setFreePoints(int value){}
int getFreePoints(){ return 0; }
void spendFreePoints(Stats stat, int amount){}
}
class Edge
{
private Map<Stats, Integer> map = new HashMap<>();
private int freePoints = 0;
void setMax(Stats stat, int value){}
int getMax(Stats stat, int value){ return 0; }
void setFreePoints(int value){}
int getFreePoints(){ return 0; }
void spendFreePoints(Stats stat, int amount){}
}
}
It is not implemented yet of course, but I want to know what is a correct version of changing for example Player's Pool. I can imagine following scenarios:
Player has exactly the same methods as Pool class which are something like
public class Player
{
// something above
void setAvailablePool(Stats stat, int value){ statistics.pool.setAvailable(stat, value); }
}
This solution seems to be ok but then in Player class I would have a lot of 1-line methods which would just redirect orders to composed fields.
I could transfer pool and edge to the Player class and make them public final but I read that mutable objects should be rather private.
Those 2 are my first thoughts, but I wanted to ask generally how to create interface in class when we use composition.
One-line methods are not a problem, but what makes your solution #1 unsatisfying is the violation of the Law of Demeter (statistics.pool.setXXXX). It might be better to have a statistics.setAvailableInPool() method (or to use your idea #2). I can' t offer more help with the specific implementation because It's not very clear what your Pool and Edge classes are supposed to do (or why they're so similar to each other but do not implement a common interface).
In answer to your general question about creating interfaces for composition, take a look at the SOLID principles. Basically, you should think about what behaviors you need from your dependencies, name those behaviors clearly, and depend on the interface rather than the concrete class. That makes the code easier to understand and easier to change in one place without having to change it everywhere.
During a Java course in my University we teach this example. While I certainly understand how this works, I fail to imagine a real life example where this practice might be useful. In my eyes it makes the code harder to understand. More specifically, is there a certain benefit in declaring an object using a class and assign it to another class (Small smallBig = new Big();) and can you give me a simple scenario where this practice might be useful?
The code:
public class Small {
public int value;
public Small() {value = 10;}
public int getValue() {return value;}
}
public class Big extends Small {
public int value;
public Big() {value = 40;}
public int getValue() {return value-10;}
}
public class Main {
public static void main (String args[]) {
Small small = new Small();
Small smallBig = new Big();
Big big = new Big();
System.out.println(small.getValue());
System.out.println(smallBig.getValue());
System.out.println(big.getValue());
System.out.println(small.value);
System.out.println(smallBig.value);
System.out.println(big.value);
small = (Small) big;
System.out.println(small.getValue());
System.out.println(small.value);
big = (Big) small;
System.out.println(big.getValue());
System.out.println(big.value);
}
}
The output:
10
30
30
10
10
40
30
10
30
40
Creating a method that operates on both Bigs and Smalls will help to illustrate the point better.
Assuming the same class definitions you already used in the question, you can create a method that prints both getValue() and value. Because Big extends Small, you need only one method.
public void printValues(Small val) {
System.out.println("getValue() == " + val.getValue());
System.out.println("value == " + val.value);
}
If you didn't have that relationship, and ability to assign Big objects to Small variables (remember: passing a value to a method is the same as assigning a variable), you'd need to have two different methods to handle this situation.
It helps to think of the extends keyword as meaning A Big is a more specific type of Small. In general, it's best to write methods that handle things using the least specific type that you can, because it will allow that method to handle situations you haven't even imagined yet.
For example, suppose that somewhere down the line, somebody decided to write
class Medium extends Small {
public Medium() {value = 20;}
public int getValue() {return value-5;}
}
The printValues() method can already handle this class, even though we didn't know about Mediums when we wrote it.
I think in this senario it'd be useful:
public class Person{
Mobility mobility;
Person(Mobility mobility){this.mobility = mobility;}
}
public class Mobility{
int speed;
public Mobility(int speed){this.speed = speed;}
}
public class Car extends Mobility{
public Car(int speed){super(speed);}
}
public class Main {
public static void main (String args[]) {
Car ferrari = new Car(1000);
Person john = new Person(ferrari);
}
}
Hope i could help you.
Well in this case you are using getValue as Template method "http://en.wikipedia.org/wiki/Template_method_pattern"
Let take you example with little twist
public class Small {
public int value;
public Small() {value = 10;}
public int getValue() {// this method fetches data from database}
}
public class Big extends Small {
public int value;
public Big() {value = 40;}
public int getValue() {//this method fetches data from xml}
public class Big2 extends Small {
public int value;
public Big() {value = 40;}
public int getValue() {//this method fetched data from some server}
}
As u can see the implementation of getValue is changing. Each sub class provides its own implementation of getValue.
Thus it gives my super class an opportunity to use different implementation of this method at run time (in you case). I Hope it makes it clear. Have a look at Template method pattern , you will get a better idea.
I would like to ask you some tips about this java scenario:
I have a simple interface called Sequence that performs some basic operation. Now I would like to implement some additional methods in a separate class, called SequenceWrapper, that implements the Sequence defined above. Here is some example code that looks like my real code:
public interface Sequence {
public void methodOne();
public int methodTwo();
}
public abstract class SequenceWrapper implements Sequence {
private wrappedSequence = null;
public SequenceWrapper(Sequence sequence){
this.wrappedSequence = sequence;
}
public void methodOne(){
wrappedSequence.methodOne();
}
public int methodTwo(){
return wrappedSequence.methodTwo();
}
}
public class ConcreteWrapper extends SequenceWrapper {
public ConcreteWrapper(Sequence sequence){
super(sequence);
}
// Just an example
public int addMethodOne(){
int a = super.methodTwo();
return a + 3;
}
}
Now if I want to implements a class with another method (say 'addMethodTwo()') I can simply extends the 'ConcreteWrapper' class and add only the new method:
public class ConcreteWrapperTwo extends ConcreteWrapper {
public ConcreteWrapperTwo(Sequence sequence){
super(sequence);
}
public int addMethodTwo(){
int a = super.methodTwo();
return a + 30;
}
}
What do you think? Is this code correct or it's preferable another strategy??
Thanks in advance
First, your private wrappedSequence = null; has no type.
I suppose you meant private Sequence wrappedSequence = null;
Second, in your example you will never be able to instantiate any of the classes, since all of them receive another Sequence in the constructor and there is no way of create the first instance of Sequence.
Third, composition over inheritance is a good approach, if you really need it. Usually you wrap an object when you need to hide or protect the access to the wrapped object. In your case, within the wrapper you are exposing all of the methods of the wrapped object. You then create new methods that will affect the wrapper object, but not the wrapped one.
What you probably need is just a normal inheritance scenario:
I would like to walk you through you a breakdown for this Java scenario:
I have a simple interface called Sequence that performs some basic operation. Now I would like to implement some additional methods in a separate class, called SequenceWrapper that implements the Sequence as defined above. Here is some example code to explain what I mean:
public interface Sequence {
public void methodOne();
public int methodTwo();
}
public abstract class AbstractSequence implements Sequence {
public SequenceWrapper( ){ }
public void methodOne(){
//basic behavior here
}
public int methodTwo(){
//basic behavior here
}
}
public class ConcreteSequence extends AbstractSequence {
public ConcreteSequence ( ){
super( );
}
// Just an example
public int addMethodOne(){
int a = methodTwo();
return a + 3;
}
}
public class ConcreteSequenceTwo extends AbstractSequence {
public ConcreteSequenceTwo( ){
super( );
}
public int addMethodTwo(){
int a = methodTwo();
return a + 30;
}
}