I'm currently working on a project to make a simple 2d platformer in Java for uni, and the way we've been suggested to handle levels is to create an abstract level class, and then other classes implementing it for each individual level, so:
abstract class GameLevel {}
class Level1 extends GameLevel {}
class Level2 extends GameLevel {}
etc...
And then in my main class, I have a variable to keep track of the current level number, and code to move on to the next level, which essentially is:
public void goNextLevel() {
world.stop();
if (level == FINAL_LEVEL) {
// win code
} else {
level++;
world = new Level/*next level number*/();
}
}
And I was wondering if there was a way to take the variable containing the level number and add it on to the end of the class call, to save having to have a stack of if else statements.
Thanks for any help in advance
edit: The reason I'm not keen on putting all of it in one class and then using a variable in that to change the level is that each level has to have a relatively large number of entities, which each take a few lines to set up, and adding all of the levels in one file would lead to hundreds of lines of code which would be difficult to maintain
You would do so:
try {
final Class<?> clazz = Class.forName("your.package.Level" + levelInteger);
final Constructor<?> ctor = clazz.getConstructor();
final GameLevel level = (GameLevel) ctor.newInstance();
System.out.println(level.getClass().getName());
} catch (final Exception e) {
e.printStackTrace();
}
Source and explanation: https://stackoverflow.com/a/6094602/8160563
Assuming that there in only ever one object of each LevelN class, the simplest thing to do would be to store them into an array
GameLevel[] levels = new GameLevel[5];
levels[0] = new LevelOne();
levels[1] = new LevelTwo();
And then have a little helper method to retrieve them
GameLevel getNextLevel(int currentLevel) {
return levels[currentLevel];
}
Related
In most radio devices, we can configure the wave which we want to explore and listen to stations using the demodulation mode compatible with this type.
There are at least two types AM and FM. We can model the radio device in this case as the following:
class RadioDevice {
void demodulate (String m) {
if(m.equals("FM")
/* FM modelation */
else if(m.equals("AM")
/* AM modelation */
}
}
How can I apply the strategy pattern in this case?
Why don't you use polymorphism ?
Make an interface:
interface Radio {
void modulate();
}
And than implement 2 classes:
FMRadio implements Radio{
public void demodule(){
//FM modulation
}
}
AMRadio implements Radio{
public void demodule(){
//AM modulation
}
}
And than, in your main, you could go:
Radio myRadio = new FMRadio();
myRadio.demodule();
If you can have an interface that covers the contract for both AM and FM demodulation, you could use the Strategy pattern:
Demodulator d; // interface Demodulator { byte[] demodulate(); }
switch(m) {
case "AM":
d = new AMDemodulator();
break;
case "FM"
d = new FMDemodulator();
break;
default:
throw new IllegalArgumentException("Unsupported type '"+ m + "'"); // you could use an Enum instead of a String
}
d.demodulate(waves);
This allows you to switch the Demodulator part on the fly while keeping the rest of the program logic in common (no duplication).
Check this repo (not mine) for design patterns and examples: https://github.com/iluwatar/java-design-patterns
To make it a proper Strategy pattern, I would add using a Context class to the previous answer of #Ladislav_M, that will wrap & encapsulate executing a particular strategy and give more flexibility to the code:
class Context {
private Radio radio;
public Context(Radio radio) {
this.radio = radio;
}
public Object runStrategy() {
radio.demodulate();
// do any other stuff you want
return ...
}
}
The execution in main would become more convenient:
Context context = new Context(new FmRadio());
Object result = context.runStrategy();
Or you can inline the above:
Object result = (new Context(new FmRadio())).runStrategy();
Of course, you can choose the implementation of Radio in a switch block and just pass it as a variable to the Context's constructor.
This is not a good use case for Strategy design pattern, its simple inheritance case. Strategy is used where the state of the object does not change but different algorithms apply at different times. e.g. Paypackage computation for different roles of employees (e.g. Temporary, Permanent etc.). Important point here is Temporary employee can become Permanent one day.
In the above case AM will never become FM in its life time. hence Strategy is not right pattern for it. These are (probably) different classes with common behavior (if present) can be shifted to base class. If they show a common contract with clients then even interface will do the task.
I am making a multiplayer game which makes heavy use of a serialisable Event class to send messages over a network. I want to be able to reconstruct the appropriate subclass of Event based on a constant.
So far I have opted for the following solution:
public class EventFactory {
public static Event getEvent(int eventId, ByteBuffer buf) {
switch (eventId){
case Event.ID_A:
return EventA.deserialise(buf);
case Event.ID_B:
return EventB.deserialise(buf);
case Event.ID_C:
return EventC.deserialise(buf);
default:
// Unknown Event ID
return null;
}
}
}
However, this strikes me as being very verbose and involves adding a new 'case' statement every time I create a new Event type.
I am aware of 2 other ways of accomplishing this, but neither seems better*:
Create a mapping of constants -> Event subclasses, and use clazz.newInstance() to instantiate them (using an empty constructor), followed by clazz.initialiase(buf) to supply the necessary parameters.
Create a mapping of constants -> Event subclasses, and use reflection to find and call the right method in the appropriate class.
Is there a better approach than the one I am using? Am I perhaps unwise to disregard the alternatives mentioned above?
*NOTE: in this case better means simpler / cleaner but without compromising too much on speed.
You can just use a HashMap<Integer,Event> to get the correct Event for the eventID. Adding or removing events is going to be easy, and as the code grows this is easy to maintain when compared to switch case solution and speed wise also this should be faster than switch case solution.
static
{
HashMap<Integer,Event> eventHandlerMap = new HashMap<>();
eventHandlerMap.put(eventId_A, new EventHandlerA());
eventHandlerMap.put(eventId_B, new EventHandlerB());
............
}
Instead of your switch statement Now you can just use :
Event event = eventHandlerMap.get(eventId);
if(event!=null){
event.deserialise(buf);
}
If you're not afraid of reflection, you could use:
private static final Map<Integer, Method> EVENTID_METHOD_MAP = new LinkedHashMap<>();
static {
try {
for (Field field : Event.class.getFields())
if (field.getName().startsWith("ID_")) {
String classSuffix = field.getName().substring(3);
Class<?> cls = Class.forName("Event" + classSuffix);
Method method = cls.getMethod("deserialize", ByteBuffer.class);
EVENTID_METHOD_MAP.put(field.getInt(null), method);
}
} catch (IllegalAccessException|ClassNotFoundException|NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
public static Event getEvent(int eventId, ByteBuffer buf)
throws InvocationTargetException, IllegalAccessException {
return (Event) EVENTID_METHOD_MAP.get(eventId).invoke(null, buf);
}
This solution requires that int ID_N always maps to class EventN, where N can be any String where all characters return true for the method java.lang.Character.isJavaIdentifierPart(c). Also, class EventN must define a static method called deserialize with one ByteBuffer argument that returns an Event.
You could also check if field is static before trying to get its field value. I just forget how to do that at the moment.
For some reason .get() isn't a valid method in my code. Can somebody point out the error? (Sorry for the improper object names (wasn't planning on sharing this code))
public class Summon_Tester
{
public static void main (String [] Args)
{
Summoned_Bin Bin = new Summoned_Bin();
Bin.addToBin();
System.out.println(Bin.get(0));
}
}
Summoned_Bin code
import java.util.ArrayList;
public class Summoned_Bin
{
ArrayList<Summon> Bin = new ArrayList<Summon>();
Summoned_Bin()
{
}
void addToBin()
{
Summon summoned = new Summon();
int index = 0;
while (Bin.get(index) != null)
{
index++;
}
Bin.add(index , summoned );
}
}
The Summoned_Bin isn't an ArrayList as it does not extend the ArrayList class. Rather, it contains an ArrayList. Know that this is fine, it's quite OK to enhance a class through composition and not inheritance, but just don't try to use any ArrayList methods directly on it.
You have two common solutions:
You can make it extend ArrayList, but I'm not sure that this is the best thing to do, or
You can give it public methods that allow outside classes to extract information.
For example, give it a get(...) method:
public Summon get(int index) {
return Bin.get(index);
}
Edit
As nachokk rightly suggests, you will want to learn and follow Java code conventions, as doing this will make it much easier for others to understand your code.
This is a bit tricky to explain. I have a class A:
public class A {
private Integer a1;
private Integer a2;
// getters and setters.
}
There is a static class B that returns my class A:
public static class B {
public static A getCurrentA() {
return a;
}
}
I need to find all usages of class A returned by B. So let's say class C calls c.setA(B.getCurrentA()) and then further along there's a call to c.getA().getA2();, I'd want to find all of these.
In the real scenario, I have 217 different classes that call B.getCurrentA(). I can't manually follow all the calls in Eclipse and find out which methods are getting called.
Eclipse call hierarchy view only shows me all calls to B.getCurrentA().
How can I achieve this?
EDIT
Chris Hayes understood what I want to do. In order to refactor some really bad legacy code without breaking the whole system, I need to first fine-tune some queries using Hibernate's projections (every mapped entity in the system is eagerly loaded, and many entities are related, so some queries take a LONG time fetching everything). But first I need to find which properties are used so that I don't get a NullPointerException somewhere...
Here's an example of what I'd have to do manually:
Use Eclipse's Search to find all calls to B.getCurrentA();
Open the first method found, let's say it's the one below:
public class CController {
C c = new C();
CFacade facade = new CFacade();
List<C> Cs = new ArrayList<C>();
public void getAllCs() {
c.setA(B.getCurrentA()); // found it!
facade.search(c);
}
}
Open the search method in the CFacade class:
public class CFacade {
CBusinessObject cBo = new CBusinessObject();
public List<C> search(C c) {
// doing stuff...
cBo.verifyA(c);
cBo.search(c); // yes, the system is that complicated
}
}
Open the verifyA method in the CBusinessObject class and identify that field a2 is used:
public class CBusinessObject {
public void verifyA(c) {
if (Integer.valueOf(1).equals(c.getA().getA2())) {
// do stuff
else {
// something else
}
}
}
Repeat steps 2-4 for the next 216 matches... Yay.
Please help.
If you want to make any source code changes/refactoring you will have to manually find all usages and apply your code changes;
Any way, I have two different aproach
Static search
You can simply do Text Search in eclipse to find the occurance of getA2() . It will directly take you to the Caller method (here CBusinessObject.verifyA()) -but it will give you every getA2() occurances, may be from different class
Run time search
Use java instrumentation API to change the byte code at run time on your required method to find invoking class and run as java agent - Enable you to identify the caller with out touching the existing code base and very useful especially when you don't have access to source code.
Here you go how to implement
Step 1- Write Agent main class to initiate instrumentation
public class BasicAgent {
public static void premain(String agentArguments, Instrumentation instrumentation){
System.out.println("Simple Agent");
FindUsageTransformer transformer = new FindUsageTransformer ();
instrumentation.addTransformer(transformer,true);
}
}
Step 2 -Write a ClassFileTransformer implementation and capture the method
public class FindUsageTransformer implements ClassFileTransformer{
Class clazz = null;
public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
if(className.equals("A")){
doClass(className, classBeingRedefined, classfileBuffer);
}
return classfileBuffer;
}
private byte[] doClass(String name, Class clazz, byte[] b) {
ClassPool pool = ClassPool.getDefault();
CtClass cl = null;
try {
cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
CtMethod method = cl.getDeclaredMethod("getA2");
// here you have lot of options to explore
method.insertBefore("System.out.println(Thread.currentThread().getStackTrace()[0].getClassName()+ Thread.currentThread().getStackTrace()[0].getMethodName());");
b = cl.toBytecode();
} catch (Exception e) {
System.err.println("Could not instrument " + name
+ ", exception : " + e.getMessage());
} finally {
if (cl != null) {
cl.detach();
}
}
return b;
}
Step 3- create jar file for agent classes ( you have to set manifest file with premain class, and add javaassit jar) snippet of build file is given - you can do it by manually as well
<jar destfile="build/jar/BasicAgent.jar" basedir="build/classes">
<manifest>
<attribute name="Manifest-Version" value="1.0"/>
<attribute name="Premain-Class" value="com.sk.agent.basic.BasicAgent"/>
<attribute name="Boot-Class-Path" value="../lib/javassist.jar"/>
</manifest>
</jar>
Step 4- Run your main application with java agent - before that set VM arguments to load agent
-`javaagent:D:\softwares\AgentProject\AgentLib\build\jar\BasicAgent.jar`
Pre requisite : you would need javassist.jar in the class path.
Depending on the IDE you are using this problem is simpler to find.
Eclipse IDE has one of the most potential Call Hierarchy modules existing, you just need to put the mouse in the method declaration that you want to find and execute Ctrl + Alt + H
This will give you the entire hierarchy of which method is using the method you want to analyze.
Also the Call Hierarchy module offers a mode where you can find the methods that your method is calling.
Some extra info: http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Freference%2Fcdt_u_call_hierarchy_view.htm
In IntelliJ IDEA, if you want to find usages of c.getA().getA2(); right-click on A.a2 and choose "find usages." Similarly for A.a1 and B.getCurrentA(). Unused fields and methods show up in a different color in IDEA. I've heard that IntelliJ has more refactoring power than Eclipse, but I bet Eclipse does the same thing, just slightly differently.
Also, using grep, find, and sed, you can search for the appropriate methods, just in files that are in the same package as A or that import A, or spell it out by name.
I hope I understood your question correctly. I think you can use grep -Irns function to find the calls. You can grep for getA().getA2(). That will return lines from where functions are called along with line numbers.
Rather than scanning for all references to the method getCurrentA do a scan for all references to the Class A.
This will show you everywhere that class is used within your program and you will probably find it is easier to go through and scan that list by hand and decide if you need to act on each result found than trying to do anything fancy.
The easiest way to find Call Usage is using references in eclipse,but there is a funny way
:
Change method name to B.getCurrentAA()
Build your Project
Your Project compiles with error
Go to Marks Part and see usage Error And Find Usage Of your method
I think IntelliJ can solve your problem. It have an "Analyze dataflow" feature and I think it is doing what you are looking for:
Here is my sample code:
public class Main {
private static A a = new A(); //nevermind the way it is initialized
public static A getA(){
return a;
}
public void method(){
A myA = getA();
Integer a1 = myA.getA1(); //this line is found
Integer a2 = myA.getA2(); //this line is found
}
public void anotherMethod(){
A myA = new A();
Integer a1 = myA.getA1(); //this line is NOT found
Integer a2 = myA.getA2(); //this line is NOT found
}
}
Running the "Analyze dataflow from here" (with cursor on return a; line) give me this:
Sorry to provide you only a solution with IntelliJ (tested with IntelliJ-13 Ultimate Edition)
I have a set of classes that implement a particular interface and I have a set of checkboxes. I want to throw an error if no checkboxes are selected. If atleast one or more checkboxes are selected, then it should create objects associated with that checkbox.
This is how I done.
interface U { ... }
class A implements U { ... }
class B implements U { ... }
class C implements U { ... }
class Main {
//....
//....
public void findSelectedCheckBoxesAndCreateObjects() {
if(!(checkboxA.isSelected() || checkboxB.isSelected() || checkboxC.isSelected()) {
System.out.println("No checkboxes selected");
return;
}
//if any selected, create associated object
if(checkboxA.isSelected()) new A(file);
if(checkboxB.isSelected()) new B(file);
if(checkboxC.isSelected()) new C(file);
}
}
Now I have 3 problems.
This is just a sample code. Original has 8 checkboxes and classes with more coming.
I can't keep adding || checkboxD.isSelected() every time I have a new class for checking it.
Same thing. I can't keep adding if(checkboxD.isSelected()) new D(file); for every class.
It is very inelegant. Can I have some kind of loop that removes the redundant code?
Please give me your suggestions.
Thank you.
You should use a collection structure to hold your checkboxes and those related classes.
Using a Map you could do something like this:
Map <JCheckBox,Class<U>> uCheck = new HashMap<JCheckBox,Class<U>>();
// add your checkboxes and U-classes to the map
uCheck.put(checkBoxA, A.class);
Now, it's quite easy to get a collection of the classes that need to be instantiated based on the checkbox status:
public Collection<Class<U>> getEnabledClasses(<JCheckBox,Class<U>> checkMap) {
List<Class<U>> result = new LinkedList<Class<U>>();
for (Map.Entry<JCheckBox,Class<U>> entry:checkMap.entrySet()) {
if (entry.getKey().isSelected()) {
result.add(entry.getValue());
}
}
}
Now, a call to getEnabledUs(uCheck) returns a collection of the selected classes. If the collection is empty, there's no selection, hence nothing to do.
for (Class<U> u:getEnabledClasses(...)) {
Constructor<U> cons = u.getConstructor(...);
U instance = cons.newInstance(fileparameter);
instance.doSomething(...);
}
That should get you started.
(*) Disclaimer: this is non-tested code. Rather pseudo-code with crisp detail only where needed.