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.
Related
I am trying to print a final class with static fields on the console, in json format. I am using eclipse.
Stats is a final class that keeps track of object instances that are created or archived. E.g. number of Member instances, number of localities instances etc.
public final class Stats {
public static Integer numMembers = 0;
public static Integer numLocalities = 0;
public static Integer numTowns = 0;
public static void incrementMembers () { numMembers ++; }
public static void incrementLocalities () { numLocalities ++; }
public static void incrementTowns () { numTowns ++; }
}
I ran into problems when I tried to print in json. It does not recognize Stats as an Object instance, which is understandable. Is there a way to print the current state of the Stats class in json?
public static void print () {
System.out.println(GsonBuilder().setPrettyPrinting().create().toJson(Stats));
}
Your current approach will not work with JSON (or any other) serialization, and cannot be made to work the way you want.
A global static object is an anti-pattern as it introduces unwanted coupling into your codebase. There are two approaches to solve this problem, Dependency Injection and Singleton. In both cases, your "statistics" object is a normal object with non-static fields.
public final class Stats {
private int numMembers = 0;
private int numLocalities = 0;
private int numTowns = 0;
public void incrementMembers () { numMembers ++; }
public void incrementLocalities () { numLocalities ++; }
public void incrementTowns () { numTowns ++; }
// Getters...
}
(not sure why you were using Integer, it's not necessary here)
Dependency Injection requires a framework like Spring. If you're not already using Spring then it may be too much change and learning-curve all at one time for you to take on. But it is the best way long-term. An explanation of DI is beyond the scope of an answer here, but the principle is that the framework takes care of instantiating the object and "injecting" it wherever it is needed.
The lighter-weight alternative is the "singleton" pattern (look it up, it is well-documented), where the object contains one static member reference to the single instance that gets created the first time you access it.
public final class Stats {
...
private static Stats instance = null;
public static Stats getInstance()
{
if (instance == null)
instance = new Stats();
return instance;
}
}
(The above is simplistic and ignores threading concerns, study the pattern before using)
Then wherever you need a reference to the (single) Stats instance you do
Stats stats = Stats.getInstance();
In either case you have a real instance that can be serialized.
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;
}
}
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 create my own class, which had 3 fields. The first field - integer, the second would take objects (Strings, Lists), and the third would take integers. I do not understand two things.
How to organize the storage of variables. I need to write a method in which the Array or List will save these values? How to save in object values?
For second field. If the input is a String or a List so what Type is needed? and if I want to take as primitive types, then what? How to save object?
public class Record {
private int[] number;
private int[] count;
private Object[] code;
public void add(int newNumber, List<String> newCode, int newCount){
return;
};
public void add(List<String> newCode, int newCount,){
return;
};
This doesn't work.
Object nobj = new Object();
nobj = "ss";
Okay. It appears to me that you've misunderstood the purpose of your class. You've written a class to simulate a single Record, but you've written Record to store many values.
Let's re-arrange your class structure a little
public class Record {
private int number;
private int count;
private Object code;
public Record(int number, int count, Object code)
{
this.number = number;
this.count = count;
this.code = code;
}
Then you can create a class, to manage the interface between the Record class, so for example:
public class Storage
{
List<Record> records;
public Storage()
{
this.records = new ArrayList<Record();
}
public void addRecord(int number, int count, Object code)
{
records.add(new Record(number, count, code));
}
}
That way, you're not messing about with lots of different arrays, which are horrible to try to keep track of, Everything is neatly wrapped up inside your objects.
Your issue with the second attribute
Now, it seems you want to store anything in this variable. This is somewhat more complex than your original problem, but I think that Generics will answer your problem for you. I won't write the code for you, but what I can do is give you a demonstration.
public class GenericExample<T>
{
T object;
public GenericExample(T object)
{
this.object = object;
}
}
Okay, so what I've done here is simple. I've created a new class, GenericExample, and I've said that this class has a special type, T. This type is defined at run time, and means you can define plenty of different values. For example.
GenericExample<String> example = new GenericExample<String>("This is a string");
GenericExample<Object> example2 = new GenericExample<Object>(new Object());
See how you can define the type, and pass it in at run time? Now think about applying it to your class structure.
If you really do not need to create your own List, avoid that. Just create your own type of data and use it as a parameter for List:
public class Record {
private int number;
private int count;
private Object code;
// Constructors, setters and getters
};
List<Record> myList = new ArrayList<>();
At the moment I'm working on a game and things are going pretty good. What keeps me busy at the moment, is making a mob spawner which spawns mobs in a certain area.
The big problem is right now, I'm not really sure how to keep track of all the mobs being spawned by the spawner, as there are different inheritances of mobs.
This is my MobSpawner class:
public class MobSpawner {
protected List<Mob> mobs;
protected Level level;
protected int timer = 0;
protected int spawnTime = 0;
protected int maxMobs = 0;
public MobSpawner(Level level) {
this.level = level;
}
}
And this is my RoachSpawner class:
public class RoachSpawner extends MobSpawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Roach>(); // Roach is an extension of Mob
}
}
This is not gonna work because the List and ArrayList must be of the same type.
So the question is, does anyone have any other ideas how to do this?
Thanks in advance!
I'm presuming that Roach extends Mob.
You can use an ArrayList<Mob> to hold Roaches. So:
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Mob>();
}
And if you just use ArrayList<Mob> in all the implementations, you can allocate it in the base instead (assuming ArrayList is always the container you want -- if you want to use other List types see kwah's answer and have subclasses create list):
public class MobSpawner {
protected final List<Mob> mobs = new ArrayList<Mob>();
...
}
And just have the subclasses use the base's list.
Instantiating the list in the base class and making it final has a bonus side-effect of letting you state the following invariants (presuming you don't violate them with reflection or anything):
A MobSpawner will never have a null mobs, and
mobs will reference the same object throughout the entire lifetime of a MobSpawner.
Being able to make those assumptions can possibly simplify some of your logic in other places.
Making it final also enforces, at compile time, that you're not inadvertently replacing it with another list somewhere.
If you are not already doing so, try taking advantage of supertypes.
In the same way that you can declare a variable to be a List and then instantiate it to be an ArrayList, try saying your List contains Character items and then fill it with specific implementations of the Characters (eg List<Character> is instantiated as ArrayList<Mob> and ArrayList<Roach>).
public abstract class Character { }
public class Mob extends Character { }
public class Roach extends Character { }
public class Spawner {
protected List<? extends Character> characters;
protected Level level;
protected int timer = 0;
protected int spawnTime = 0;
protected int maxCharacters = 0;
public Spawner(Level level) {
this.level = level;
}
}
public class RoachSpawner extends Spawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Roach>();
}
}
public class MobSpawner extends Spawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Mob>();
}
}