OOP - Interface inheriting an abstract class alternative - java

Let's say that I have an interface IMazeRoom
This interface has a function getAdjacentRooms()
Furthermore, Mazerooms have to be instanciated as IMazeRoom room1 etc.
(All of the above cannot be changed)
Let's say these classes are implementing the interface:
TrapRoom, FreeRoom, MobRoom, TreasureRoom
I want to the following functions/variables to be used in all of those subclasses
Players[] playersInRoom, setSize(), isAdditionValid(Player p)
I want to use inheritence with the three functions/variable above without modifying the interface, or duplicating the code throughout the four subclasses.
What I have tried so far
Making an abstract interface MazeRoom which implements IMazeroom, and is implemented by the four subclasses. This does not work as a constraint of this project is that the rooms have to be instantiated as IMazeroom room and doing this would lead to instantiation Mazeroom room If I wanted to use the new functions meantioned above. Also IMazeRooms cannot be modified.
Ideas
I could probably just use another interface with the functions I want to include, which would be implemented by IMazeroom, but this seems weird as this constraint should be here to teach me something, and I do not see the value in just using another interface. Furthermore, using another interface would not really cut down on code duplication, I am looking for something more like a abstract class
(The above is a completely different example from my homework task, as I want to attemp the task on my own)

Edit: Since we cannot change the interface, you can use a DefaultRoom class that implements IMazeRoom.
public class DefaultRoom implements IMazeRoom {
protected Players[] playersInRoom;
/* your standard method implementations */
public boolean isAddtionValid(Player p) {
...
}
}
public interface IMazeRoom {
...
}
Since you have to instantiate it via IMazeRoom myIMazeRoomObject = new DefaultRoom(), as long as you know which kind of Room you are handling, you can simply cast it back:
try {
DefaultRoom myRoom = (DefaultRoom) myIMazeRoomObject;
} catch(ClassCastException ex) {
// we didn't get a DefaultRoom object and now we have to handle that
}
Sidenote: The important thing to note is, that the interface only implements the necessary method getAdjacentRoom, as such it only constitutes information to some (arbitrary) layout that relies on getAdjacentRooms().
Your secondary constraints (immutable interface + instantiation) make it necessary to circumvent something that shouldn't happen with proper OO architecture.

You can seperate the common concrete implemetation into a abstact class and keep the interface.
Rough example based on "I am not allowed to change the interface though":
IMazeRoom:
public interface IMazeRoom {
Set<IMazeRoom> getAdjacentRooms();
}
Common concrete implemetation:
public abstract class CommonRoom {
private final int size;
private final Set<Player> playersInRoom;
private final Set<IMazeRoom> adjacentRooms;
protected CommonRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
this.size = size;
this.playersInRoom = playersInRoom;
this.adjacentRooms = adjacentRooms;
}
public int getSize() {
return size;
}
public Set<Player> getPlayersInRoom() {
return playersInRoom;
}
public Set<IMazeRoom> getAdjacentRooms() {
return adjacentRooms;
}
public boolean isAdditionValid(Player player) {
// Some kind of implementation returning true or false...
return !playersInRoom.contains(player);
}
}
TrapRoom:
public class TrapRoom extends CommonRoom implements IMazeRoom {
public TrapRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
super(size, playersInRoom, adjacentRooms);
}
}
TreasureRoom:
public class TreasureRoom extends CommonRoom implements IMazeRoom {
public TreasureRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
super(size, playersInRoom, adjacentRooms);
}
}
... same implementation as TreasureRoom for additional rooms.
Comment: Now all rooms are treated as IMazeRoom...

Related

How to alter the design so that entities don't use injections?

I've read and came to realize myself that entities (data objects - for JPA or serialization) with injections in them is a bad idea. Here is my current design (all appropriate fields have getters and setter, and serialVersionUID which I drop for brevity).
This is the parent object which is the head of the entity composition graph. This is the object I serialize.
public class State implements Serializable {
List<AbstractCar> cars = new ArrayList<>();
List<AbstractPlane> planes = new ArrayList<>();
// other objects similar to AbstractPlane as shown below
}
AbstractPlane and its subclasses are just simple classes without injections:
public abstract class AbstractPlane implements Serializable {
long serialNumber;
}
public class PropellorPlane extends AbstractPlane {
int propellors;
}
public class EnginePlane extends AbstractPlane {
List<Engine> engines = new ArrayList<>(); // Engine is another pojo
}
// etc.
In contrast, each concrete type of car requires a manager that holds some behavior and also some specific form of data:
public abstract class AbstractCar implements Serializable {
long serialNumber;
abstract CarData getData();
abstract void operate(int condition);
abstract class CarData {
String type;
int year;
}
}
public class Car1 extends AbstractCar {
#Inject
Car1Manager manager;
Car1Data data = new Car1Data(); // (getter exists per superclass requirement)
void operate(int i) { // logic looks weird but makes the example
if (i < 0)
return manager.operate(data);
else if (i > 1)
return manager.operate(data, i);
}
class Car1Data extends CarData {
int property1;
{
type = "car1";
year = 1;
}
}
}
public class Car2 extends AbstractCar {
#Inject
Car2Manager manager;
Car2Data data = new Car2Data();
void operate(int i) {
if (i < 31)
return manager.operate(data);
}
class Car2Data extends CarData {
char property2;
{
type = "car2";
year = 12;
}
}
}
// etc.
The CarxManager are #Stateless beans which perform operations on the data (the matching CarxData) given to them. They themselves further use injections of many other beans and they are all subclasses of AbstractCarManager. There are O(100) car types and matching managers.
The issue when serializing the State is that serializing the list of abstract cars does not play well with the injections in the subclasses. I'm looking for a design that decouples the injection from the data saving process.
My previous related questions: How to serialize an injected bean? and How can I tell the CDI container to "activate" a bean?
You can use the repository pattern. Place your business logic into a service and inject the repository (which abstracts the persistence mechanism) and manager into that. The repository hides the persistence implementation details from the business service and the entities are just simple POJOs.
It would look something like the below with Foo being the id of the entity Bar:
public class CarService {
#Inject
CarRepository carRepository;
#Inject
CarManager manager;
piblic void operate(final Foo foo) {
Bar myBar = carRepository.retrieve(foo);
manager.doSomethingTo(myBar);
carRepository.persist(myBar);
}
}
See also: Repository Pattern Step by Step Explanation, http://deviq.com/repository-pattern/. Some frameworks such as Spring Data JPA or deltaspike already implement the repository pattern for you, all you need to do is provide an interface like the following and they generate the implementation in the background:
#Repository
public interface CarRepository extends EntityRepository<Car, UUID> {}
Mark in answer to your request for more detail I am going to provide a remodeled solution because the example in the question really did not make sense to me and exhibits quite a few anti-patterns which lead to problematic software.
To find a good solution to the problem touches on a lot of different considerations, many of which are very large topics with many books written about them, but I will try my best to illustrate my thinking based on these to solve the above problem.
And apologies as I have no doubt you are aware of many of these, but I shall assume limited knowledge for the sake of clarity.
The first step in solving this problem is not about code, but about the model itself, model driven development is covered extensively in Eric Evan's book as mentioned in the comments below. The model should drive the implementation and should also exist on its own tier as part of a layered architecture and is made up of entities, value objects and factories.
Model Driven Development
In the model given in the question we have something called a State, which contains AbstractPlanes and AbstractCars. You are using JPA to persists the State which is effectively an aggregate of your planes and cars. Firstly calling anything a State in software is a bad smell because pretty much everything has some sort of state, but calling what we have here which is an aggregate the State makes even less sense.
How does one State differ from another? Is one car part of one State and another part of a different State or is it the case that all planes and cars belong to a single instance of State. What is the relationship between planes and cars in this scenario? How does a list of planes and a list of cars have any relation to a single State entity?
Well if State was actually an Airport and we were interested in how many planes and cars were currently on the ground, then this could be the correct model. If State was an Airport it would have a name or identity such as its airport code, but it does not and so...
... in this case, it seems that State is an object which is being used as a convenience to allow us to access the object model. So we are effectively driving our model by implementation considerations, when we should doing it the other way round and driving our implementation from our model.
Terms like CarData are also problematic for the same reason, creating a Car entity and then a separate object to store its Data is messy and confusing.
Failure to get the model right results in software that is at best confused and at worst completely non-functional. This is one of the largest causes of failed IT programmes and the bigger the project the harder this stuff is to get right.
Revised Model
So from the model I understand that we have Cars and we have Planes, instances of which are all unique entities with their own identity. They seem to me to be separate things and so there is no point in persisting them wrapped in some aggregate entity.
public class Plane {...}
public class Car {...}
Another consideration is the use of abstract classes in the model, generally we want to apply the principle of favoring composition over inheritance because inheritance can result in hidden behaviors and it can make a model hard to read. For example why have we got a ProperllerPlane and an EnginePlane? Surely a propeller is just a type of engine? I have greatly simplified the model:
public class Plane implements Serializable {
#Id
private String name;
private String model;
private List<Engine> engines;
The Plane is an entity with its own attributes and identity. There is no need to have additional classes which represent nothing in the real world just to store attributes. The engine object is currently an enum representing the type of engine used in the plane:
public enum Engine {
PROPELLER, JET
}
If the engine itself were to require an identity, as in real life engine serial numbers and things are tracked, then we would change this to an object. But we might not want to allow access to it except through a Plane entity instance, in which case the Plane will be known as a aggregate root - this is an advanced topic and I would recommend Evan's book for more details on aggregates.
The same goes for the Car entity.
#Entity
public class Car implements Serializable{
#Id
private String registration;
private String type;
private int year;
The above is all you need from what was provided in the question for the basis of your model. I have then created a couple of factory classes which handle creation of instances of these entities:
public class CarFactory {
public Car makePosrche(final String registrationNumber) {
Car porsche = new Car();
porsche.setRegistration(registrationNumber);
porsche.setType("Posrshe");
porsche.setYear(1986);
return porsche;
}
}
public class PlaneFactory {
public Plane makeSevenFourSeven(final String name) {
Plane sevenFourSeven = new Plane();
List<Engine> engines = new ArrayList<Engine>();
engines.add(JET);
engines.add(JET);
engines.add(JET);
engines.add(JET);
sevenFourSeven.setEngines(engines);
sevenFourSeven.setName(name);
return sevenFourSeven;
}
public Plane makeSpitFire(final String name) {
Plane spitFire = new Plane();
List<Engine> engines = new ArrayList<Engine>();
engines.add(PROPELLER);
spitFire.setEngines(engines);
spitFire.setModel("Spitfire");
spitFire.setName(name);
return spitFire;
}
}
What we are also doing here is separating out concerns as according to the Single Responsibility Principle each class should only really do one thing.
Now that we have a model we need to know how to interact with it. In this case we would most likely if using JPA persist the Cars in a table called Car and the Planes likewise. We would provide access to these persisted entities via repositories, CarRepository and PlaneRespository.
You can then create classes called services which inject the repositories (and anything else you require) to perform CRUD (Create Read Update Delete) operations on the instances of cars and planes and also this is the point where you can apply your business logic to these. Such as your method:
void operate(int i) {..}
By structuring your code this way you decouple the model (entities and value objects) from how they are persisted (repositories) from the services which operate on them as mentioned in your question:
I'm looking for a design that decouples the injection from the data saving process.
A possibility is to remove the property, so it won't be picked up by the serializers. This can be achieved be getting it programmatically.
private Car2Manager getCar2Manager() {
CDI.current().select(Car2Manager.class).get();
}
I would not consider this a clean solution, but it should be a workable "solution"
Also which might work is using JPA's #Transient:
#Inject
#Transient
Car2Manager manager;
I have not tested this, so it might not work.
What is the entry point?
Is this a web application, a rest service, a soap service, or event a scheduler?
Injection frameworks almost always separate data and service. Data are always POJO, containing absolutely no business logic. Here, assuming this is a rest-service, i will do the following:
public class SSOApplication {
public class State implements Serializable {
List<AbstractCar> cars = new ArrayList<>();
List<AbstractPlane> planes = new ArrayList<>();
// other objects similar to AbstractPlane as shown below
}
public abstract class AbstractPlane implements Serializable {
long serialNumber;
}
public class PropellorPlane extends AbstractPlane {
int propellors;
}
public class EnginePlane extends AbstractPlane {
List<Engine> engines = new ArrayList<>(); // Engine is another pojo
}
public abstract class AbstractCar implements Serializable {
long serialNumber;
abstract CarData getData();
}
public static class CarData {
String type;
int year;
}
public class Car2Data extends CarData {
char property2;
{
type = "car2";
year = 12;
}
}
public static class Car1Data extends CarData {
int property1;
{
type = "car1";
year = 1;
}
}
public static class Car1 extends AbstractCar {
#Override
CarData getData() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
public static class Car2 extends AbstractCar {
#Override
CarData getData() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
public static interface CarManager<T extends CarData> {
void operate(T car, int index);
default boolean canHandle(T carData) {
final TypeToken<T> token = new TypeToken<T>(getClass()) {
};
return token.getType() == carData.getClass();
}
}
#ApplicationScoped
public static class Car1Manager implements CarManager<Car1Data> {
public void operate(Car1Data car, int index) {
}
}
#ApplicationScoped
public static class Car2Manager implements CarManager<Car2Data> {
public void operate(Car2Data car, int index) {
}
}
#ApplicationScoped
public static class CarService {
#Any
#Inject
private Instance<CarManager<?>> carManagers;
public void operate(int index, AbstractCar car) {
final CarData carData = car.getData();
final CarManager<?> carManager = carManagers.stream()
.filter((mng) -> mng.canHandle(carData))
.findFirst()
.orElse(IllegalArgumentException::new);
carManager.operate(carData, index);
}
}
}
If you could alter your flow than perhaps you could do something like this:
class Car1InnerService {
#Inject
Car1Manager manager;
void operate(int i, Car1 car) {
if (i < 0)
return manager.operate(car.getData());
else if (i > 1)
return manager.operate(car.getData(), i);
}
}
}
I introduced some inner service which will operate on Car1 and use Car1Manager for it. Your AbstractCar class will also of course lose it's operate method because from now on your service will handle it. So now instead of calling car1.operate(i) you will have to make a call via Service like this:
public class SampleCar1ServiceUsage{
#Inject
Car1InnerService car1InnerService;
public void carManipulator(List<Car1> carlist){
int i = 0; //I don't know why you need this param therefore i just increment it
for(Car1 car: carlist){
car1InnerService.operate(i, car);
i++;
}
}
}
Of course you should introduce similar functionality for every other AbsractCar children (perhaps even extract some abstraction if necessary like for example AbsractCarInnerService which would define operate method or some interface which would do the same if you don't want any other solid methods in it). However this answer is still somehow related to #Justin Cooke answer and in my opinion you should definitely check those patterns which he mentioned in his post.

Design Patterns - One public class utilizing many hidden classes

I have gone through http://www.dofactory.com/net/design-patterns in trying to find out the most efficient to create a design pattern in which "one visible class utilizes many hidden classes" to create a fluent API. Below is the code I currently have:
public class VisibleClass {
Private OrderClass order;
private ReceiptClass receipt;
public VisibleClass makeOrder() {
if (!(order instanceof OrderClass))
order = new OrderClass();
order.make();
return this;
}
public VisibleClass printReceipt() {
if (!(receipt instanceof ReceiptClass))
receipt = new ReceiptClass();
receipt.print();
return this;
}
}
class OrderClass implements IOrder {
public void make() {}
}
class ReceiptClass implements IReceipt {
public void print() {}
}
interface IOrder { void make(); }
interface IReceipt { void print(); }
Here is how I am currently using the API:
public static void main(String[] args) {
VisibleClass x = new VisibleClass();
x.makeOrder().printReceipt();
}
It this a good approach? Can a better approach be used for it?
*EDIT: Also, I should add that the VisibleClass will implement all methods of the hidden classes.
Your approach is quite good. Here some recommendations:
1 Change class member types to their interfaces as for 'Program to an interface, not an implementation' principle:
public class VisibleClass {
private IOrder order;
private IReceipt receipt;
2 Do you really need to check class types in makeOrder and printReceipt methods ? Creating instances after null check seems enough:
public VisibleClass makeOrder() {
if (null == order)
order = new OrderClass();
order.make();
return this;
}
public VisibleClass printReceipt() {
if (null == receipt)
receipt = new ReceiptClass();
receipt.print();
return this;
}
3 This approach is valid until methods of VisibleClass will be called by a single thread. If you're going to place it in a multi-thread program, you should ensure that there are only one instances of OrderClass and ReceiptClass each. There are 3 ways you can follow:
a. Create instaces of OrderClass and ReceiptClass in constructor and make VisibleClass singleton.
b. Make OrderClass and ReceiptClass singleton and remove new lines.
c. Create instances surrounded with synchronized block in makeOrder and printReceipt methods.
one visible class utilizes many hidden classes
don't do that with business classes. Fluent syntax's is great for configuration etc, but not for plain business code.
The reason is that the class itself losses control over it's state which can put it in an inconsistent state (i.e generate faulty results).
There is even a principle called Law of Demeter which is about just that.
If you have a business requirement that a receipt should be printed on a new order you should just return it as a return value.
var receipt = visibleClass.makeOrder();
As for using interfaces for entity/business classes, why do you do that? why would you want to abstract away those? The usually do not have any other dependencies or different types of implementations.
You can try using the Facade Design pattern
Or may be try using a Decorator Pattern

Java: How do I write a generic method?

let's say that I have several Creature subclasses, and that they have each have some sort of getGroup() method that returns a List<Creature>.
What I mean by "some sort of" .getGroup() method is that the name of this function varies between subclasses. For instance, Wolfs travel in packs, so they have a getPack() member. Fish travel in schools, so they have a .getSchool() member, Humans have a getFamily() member, and so on.
.getGroup() doesn not exist in Creature, and it cannot be added to the interface. None of these clases can be edited.
I'm writing a method to print the number of Creatures in their group. How would I do this?
Essentially, I'm looking to condense these two functions into the same thing:
public void PrintSchoolSize(Fish dory) {
System.out.print(dory.getSchool().size());
}
public void PrintHiveSize(Bee bee) {
System.out.print(bee.getColony().size());
}
...into the following function:
public void printGroupSize( Class<? extends Creature> cree,
FunctionThatReturnsList getGroup() ) {
System.out.print(cree.getGroup().size();
}
I'd imagine I need to pass in a second argument (function pointer?) to void printGroupSize. Any help is very appreciated, thanks!
EDIT Thank you all for the help. This is just a simplification of the real problem I'm trying to solve. Long, overly complex problems are tougher to answer, so I posed this simpler scenario.
The only answer lies in using a generic function (if that exists). The classes I'm actually working with don't have a common interface, but they all have a function that returns a List.
What you describe in your question is not much related to Java's sense of "generic methods". You could implement it with reflection (see Class.getMethod()), but I promise you that you really don't want to go there.
It would be better for Creature to declare a possibly-abstract method getGroup() that each subclass would override. You may do that in addition to providing methods with subclass-specific names, if you wish. Code that wants to obtain the group (or its size) without knowing the specific type of creature would invoke that creature's getGroup() method. That's an application of polymorphism, which seems to be what you're actually after.
If getGroup cannot be added to the Creature interface why not add another interface to your creatures?
public interface HasGroup {
Group getGroup();
}
Would mean you can create the method:
public void printGroupSize(HasGroup cree) {
System.out.print(cree.getGroup().size();
}
The simplest way is to had a getGroup() method to the Creature interface and implement it in each subclass, but it seems you cannot do that.
If you can modify the subclasses, I would actually create a new interface CreatureGroupable with a getGroupSize() and/or getGroup(). Each subclass of Creature shall implement this interface, e.g.
public interface CreatureGroupable {
CreatureGroup getGroup();
}
public enum CreatureGroup {
WOLF_PACK("pack", 30),
GEES_FLOCK("flock", 20),
FISH_SCHOOL("school", 1000),
HUMAN_FAMILY("family", 4),
...
private final String name;
private final int size;
private CreatureGroup(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() { return name; }
public int getSize() { return size; }
}
public class Wolf implements Creature, CreatureGroupable {
// methods from Creature, constructor, ...
public CreatureGroup getGroup() {
return CreatureGroup.WOLF_PACK;
}
This way, if you have a List<Creature> you can access the group of each one and do whatever you have to do, e.g.
public void printGroups(List<Creature> creatures) {
for (Creature c : creatures) {
CreatureGroup group = c.getGroup();
System.out.println("A " + group.getName() +
" has roughly " group.getSize() +
" individuals.");
}
}
If you want more flexibility, you may not use an enum and just a standard interface and class hierarchy for the groups.
Thanks to everyone for the help. Since I'm not allowed to edit any of the aforementioned classes/interfaces (I can only write external functions), I wrote the following function
public List<? extends Creature> getGroup(Object obj) {
if(obj.getClass() == Bee.class)
return ((Bee)obj).getColony();
if(obj.getClass() == Fish.class)
return ((Fish) obj).getSchool();
/* repeat for the other classes */
return null;
}
...and used it here, as so:
public void printGroupSize( Class<? extends Creature> cree ) {
System.out.print(getGroup(cree).size());
}
I have verified that this solution does indeed work, since all of the get*****() functions return a List<Creature>. This solution also shrinks my codebase significantly, and is easier to maintain than the current structure.

Trouble implementing strategy and composite pattern to give varying behaviour in a game

I'm running into real trouble trying to complete a practical that requires using strategy and composite pattern. I am trying to create a collection of vehicles which can have different behavior depending on the surface they are on. However, these vehicles can have more than one behaviour on a surface - for example, they could have snow drive and rain drive at the same time, if the weather conditions are set to snow and rain.
I have a class called AbstractVehicle, which has two concrete subclasses, Car and Boat.
I then have an interface called IBehaviour. Implementing this interface is two abstract classes called LandBehaviour and WaterBehaviour (which are the top tier of the composite pattern). Each of these have a collection of subclasses. Focussing solely on LandBehaviour, its subclasses are SnowBehaviour, StandardBehaviour and a few others including LandAssembly.
The idea was that I would put the code for the upper-tier of composite in LandBehaviour. Then, each of the concrete subclasses would have empty implementations of the add, remove and list parts of composite, with the LandAssembly class containing the code needed to actually combine various behaviours together.
This is intended to produce the result that, for example, a car could have both StandardBehaviour and SnowBehaviour at the same time.
Rather than posting large amounts of code (and there is a lot of it), I was hoping for some feedback on the basic structure I am trying to implement. I am getting a few errors right now such as null pointer exceptions and rather than spent a long time trying to fix them, I wanted to get an idea on whether the layout of the project was right to begin with.
Edit: Adding code - which generates a null pointer exception
This is my AbstractVehicle class:
public AbstractVehicle (IBehaviour behaviourIn) {
behaviour = behaviourIn;
}
public void setBehaviour(IBehaviour ib) {
behaviour = ib;
}
public IBehaviour getBehaviour() {
return behaviour;
}
public void move() {
behaviour.ensureCorrectBehaviour();
}
The car subclass:
public Car () {
super(new StandardBehaviour());
}
The IBehaviour interface:
public interface IBehaviour {
public void ensureCorrectBehaviour();
}
The LandBehaviour abstract class:
public void ensureCorrectBehaviour() {
}
public ILandBehaviour () {
}
private ILandBehaviour landBehaviour;
public ILandBehaviour (ILandBehaviour landBehaviour) {
this.landBehaviour = landBehaviour;
}
public ILandBehaviour getBehaviour() {
return landBehaviour;
}
public abstract void addBehaviour(ILandBehaviour behaviour);
public abstract void removeBehaviour(ILandBehaviour behaviour);
public abstract ILandBehaviour[] getBehaviours();
An example of a concrete behaviour subclass (RacingBehaviour):
public RacingBehaviour(ILandBehaviour landBehaviour) {
super(landBehaviour);
}
public RacingBehaviour() {}
#Override
public void ensureCorrectBehaviour() {
System.out.println("Vehicle is racing.");
}
public void addBehaviour(ILandBehaviour behaviour) {}
public void removeBehaviour(ILandBehaviour behaviour) {}
public ILandBehaviour[] getBehaviours() {
return null;
}
And finally the LandAssembly class:
public class LandAssembly extends ILandBehaviour {
private List<ILandBehaviour> behaviours;
public LandAssembly(ILandBehaviour landBehaviour) {
super(landBehaviour);
behaviours = new ArrayList<ILandBehaviour>();
}
public LandAssembly() {}
public void addBehaviour(ILandBehaviour behaviour) {
behaviours.add(behaviour);
}
public void removeBehaviour(ILandBehaviour behaviour) {
behaviours.remove(behaviour);
}
public ILandBehaviour[] getBehaviours() {
return behaviours.toArray(new ILandBehaviour[behaviours.size()]);
}
}
I am using this runner:
AbstractVehicle aCar = new Car(120);
aCar.move();
ILandBehaviour snow = new SnowBehaviour();
ILandBehaviour racing = new RacingBehaviour();
ILandBehaviour as = new LandAssembly();
as.addBehaviour(snow);
as.addBehaviour(racing);
Before I implemented the composite, everything was fine. I was able to use the client to create a new car, call its move() method, then change its behaviour, call move() again and see the difference. I'm aware however that I'm now kinda leaving the ensureCorrectBehaviour() method in my implementation of the composite pattern, which is obviously wrong. I'm also aware that after doing this, the "new" part of the Car constructor didn't work - I had to add an empty constructor each behaviour.
I can see glaring problems in the code I've created, I just don't quite see how to fix them.
If you are concerned about the design patterns, a class diagram would be extremely useful. You have many features, and you group those features into higher levels of abstractions (such as snow/land/water/etc.) But your vehicle only takes in one behavior. Does a vehicle need to be able to have multiple features? (Surely it does as you mention).
You might consider having concretely-defined strategies in your class, where each implementation of the strategy can vary.
public abstract class Bird
{
protected BirdCallStrategy callStrat;
protected FlyStrategy flyStrat;
}
public class Duck
{
public Duck()
{
callStrat = new QuackStrategy();
flyStrategy = new FlySouthForWinterStrategy(TimeOfYear);
}
}
public class Chicken
{
public Chicken()
{
callStrat = new CluckStrategy();
flyStrat = new NoFlyStrategy();
}
}
This works well if you have distinct abstractions for your strategies. In this case Flying and BirdCalling have nothing to do with each other, but they are allowed to vary by implementation at runtime (Quacking, chirping or flying, not flying, etc.)
If however, you want to create varying instances on the fly without subtyping, you might want to look into the Decorator pattern. The decorator pattern allows you to apply any combination of "features" to an instance at run-time.
So you might end up with an object that is instantiated such as:
Window decoratedWindow = new HorizontalScrollBarDecorator (
new VerticalScrollBarDecorator(new SimpleWindow()));

Loading a class based on a level/stage?

I have come across a bit of a problem. I have a class called "GameScreen" which will know what level and stage has been selected. From that I can build a string to suggest something like "level1_1" or "level1_2". The problem is how do I load this class now?
I was going to use Class.forname(string) however each level is a different class so how do I pass the new operator to the class?
I am trying to achieve something like this... world = new World(worldListener); where "World" is the class such as "level1_1".
Hope that makes sense.
Aside from the fact that there are much better ways to implement this (see the other answers, for example), this should work (not tested, ignores exceptions, may cause abdominal distention, etc.):
public World createWorld(String levelClassName, WorldListener listener) throws Exception
{
Class<?> clazz = Class.forName(name);
Constructor<World> ctor = (Constructor<World>) clazz.getConstructor(WorldListener.class);
World world = ctor.newInstance(listener);
return world;
}
You must use reflection (java.lang.reflect)
First, even if the class for each level is different, all of them should extend/implement a common superclass/interface so basic operations are available (v.g. a constructor, a startLevel() method, and so on).
With reflection, you can chose the class related to your level, instantiate it, and pass it to your engine so it invokes your class.
As a side note, I find the architecture strange. Unless there is some other reason to do this, I would suggest using a unique class for levels and loading the configuration for each level from files. It may not be suited if gameplay changes between level, though.
See the Factory Pattern. For your case you could implement a CreateLevel(String level) method which does a simple case-statement to determine which class to create or use reflection.
Um... there's 101 better ways of doing that.
Update For example:
public abstract class Level {
// or whatever your interface is
abstract public void createWorld(WorldListener worldListener);
abstract public void nextWorld();
}
public class Level1 extends Level {
public void createLevel(WorldListener worldListener) {
/** do it **/
}
public Level nextLevel() { return new Level2(); }
}
Then somewhere else:
Level cur = new Level1();
do {
cur.createLevel(worldListener);
...
cur = cur.nextLevel();
} while (cur != null);
Original
For example:
public abstract class Level {
final public int number;
public Level(int num) { this.number = num; levels[num-1] = this;/* set up level */ }
// adjust 10 to number of levels
static private Level[] = new Level[10];
static public getLevel(int num) { return levels[num-1]; }
// or whatever your interface is
abstract public void createWorld(WorldListener worldListener);
}
public class Level1 extends Level {
public Level1() { super(0); }
public void createWorld(WorldListener worldListener) {
/** do it **/
}
}
Then somewhere else:
Level.getLevel(1).createWorld();

Categories

Resources