Multiple implementations of common interface - java

I am creating an interface say 'Car'
public interface Car {
public void drive(int Speed); // for cars which do not have gears
}
which has multiple implementation like Bus, Truck and etc
Then in a main class called Trafic, the drive method of all the implementaions should be called (the order does not matter).
I have two option for Traffic Class design:
1) either use a property for every Car implementation which makes the consrtuctor hard
to maintain and ugly (with many arguments of same type and the fact that by adding new Car implementation it should be changed) like this:
public class Traffic {
private Car bus;
private Car truck;
...
public Traffic(Car bus, Car truck,...){
this.bus = bus;
this.truck = truck;
...
}
public void run(){
bus.drive();
truck.drive();
...
}
}
2) or pass a list of Car's to Traffic. Then what if i want to check something else about the Bus, so sometimes i need to find an implementation with Instance Of. It would be something like this:
public class Traffic {
private List<Car> cars;
public Traffic(Car bus, Car truck,...){
this.bus = bus;
this.truck = truck;
...
}
public void run(){
for(Car car : cars){
car.drive();
}
}
}
I feel kind of unsatisfied with either of these solutions. Is there any other solution?

what if i want to check something else about the Bus
In polymorphic design you should create a functionality delegating method that is called on the higher level and put the implementation specific logic forking there. Sometimes this means creating a whole mini-DI helper class to provide extra services to the polymorphic implementations of parent class which can make things look a bit weird but at the same time there really isn't a way around it when in OOP.
Consider the following class hierarchy:
public abstract class Vehicle {
public abstract void drive();
}
public abstract class Car extends Vehicle {
public void drive() {
System.out.println("Driving around...");
}
public void honkHorn() {...}
}
public final class Bus extends Car {
}
public final class Truck extends Car {
#Override
public void drive() {
super.drive();
honkHorn();
}
}
Here I have augmented your class hierachy with two additional features:
There is now a common super class Vehicle because maybe you want to expand to boats which are also driven but definitely not in the same way as cars.
Truck honks its horn every time it is also driven
The latter part is the important one here; one of the bigger benefits of polymorphism is introducing extra functionality like this in subclasses. If external dependencies exist and state checking is required - for example we really don't want to drive our boats on highways - you can introduce a helper on top level to provide the implementations with extra details. So, changing Vehicle like this...
public abstract class Vehicle {
public abstract void drive(Surface surface);
}
now allows us to define a Boat...
public abstract class Boat extends Vehicle {
#Override
public void drive(Surface surface) {
if (surface.isWater()) {
doDrive(surface);
}
}
// this is needed to ensure that extending classes really do implement the driving capability!
public abstract void doDrive(Surface surface);
}
which limits the applicability of all Boat implementations to only watery surfaces.
To bring all this together with your Traffic class you can now start to consider what is the proper object hierarchy for dealing with various aspects of the class modeling given here. You could for instance define that Traffic happens on Surface and the class handles only moving instances of Vehicles on Lanes and the logic would query for eg. vehicle dimensions and speed to consider such cases as when a bus can switch lanes after picking up passengers from a stop or if the lane is already filled to brim and is moving too slow to warrant a lane change at all.
To answer your question, internally you'll probably want to use a List<Vehicle> in any case as that provides ordering for your vehicles, but the Traffic class should not take in a list of vehicles as in case where Traffic represents a highway you really don't join the traffic from random spots but from specific intersections/junctions which insert the incoming vehicle to specific spot in relation to the highway. So, you probably want to create a few methods for inserting/removing Vehicles into and out from Traffic at specific points. In this scenario the internal list probably should contain wrapper objects to augment the vehicle info with the relative position of the vehicle on the lane to make inserting new vehicles easier and in general to update all the positions in one easy loop, but this post is now getting really long and I'm assuming a lot here... :)

You could use a Varargs as argument and you should use generics in your collection it is safer.
public class Traffic {
private List<Car> cars;
...
public Traffic(Car... cars){
this.cars = Arrays.asList(cars);
}
...
}
If you want to have a List which has not the limitations of the list returned by Arrays.asList() you could do that :
public class Traffic {
private List<Car> cars;
...
public Traffic(Car... cars){
this.cars = new ArrayList<>();
this.cars.addAll(Arrays.asList(cars));
}
...
}

Related

Good OO way to categorize related objects in a model in java

I have a class Vehicles with three list fields, namely:
turboVehicles : List<ITurboVehicle>,
trailerVehicle : List<ITrailerVehicle>,
vehicles : List<IVehicle>, (containing all vehicles from lists 1 and 2 and more)
where both ITurboVehicle and ITrailerVehicle extends IVehicle.
I want this class to be able to move all vehicles at the same time, and also be able to gas(), brake() them all at the same time as well. The thing is that ITurboVehicle and ITrailerVehicle are subinterfaces to IVehicle, and have further functionality that I want this class to be able to trigger, like turboOn() and Off.
Main question:
What is a good way of modeling these lists of vehicles for appropriate use in client code? I want to hide as much complexity as possible and keep it organized well in an OO sense. The vehicles and trailerVehicles lists are both updated whenever addTrailerTruck(TrailerVehicle tv) is used for example, to distinguish between them when sub-class specific methods are used. I know that the visitor pattern could have been a good choice to achieve some of the functionality that I have been looking for, but I want to try and find other solutions.
Less important, side-stepping question:
The following has more to do with the general structure I have been trying out to make the Vehicles class easy and intuative to use: I have been trying to use the composite design pattern, but it seems like the composite class has to be of the same type as the components, which has gotten me stuck sort of. Are there any ways to use the composite pattern and still be able to access all the sub-class functionality?
In my view, it is better to have just one class which manages of state of all vehicles. After doing this, your classes will correspond to the single responsibility principle of SOLID. Read more about single responsibility principle of SOLID here
Let me show an example:
public interface IVehicle
{
void Gas();
void Brake();
}
public interface ITurboVehicle : IVehicle
{ }
public interface ITrailerVehicle : IVehicle
{ }
and concrete implementation of vehicle:
public class TrailerVehicle : ITrailerVehicle
{
public void Brake()
{
throw new NotImplementedException();
}
public void Gas()
{
throw new NotImplementedException();
}
}
And vehicle manager class:
public class VehicleManager
{
public List<IVehicle> Vehicles { get; set; } = new List<IVehicle>();
public void AddTrailer(ITrailerVehicle trailerVehicle)
{
Vehicles.Add(trailerVehicle);
}
public void GasAll()
{
foreach (IVehicle vehicle in Vehicles)
vehicle.Gas();
}
}

What is the point of a “sealed interface” in Java?

Sealed classes and sealed interfaces were a preview feature in Java 15, with a second preview in Java 16, and now proposed delivery in Java 17.
They have provided classic examples like Shape -> Circle, Rectangle, etc.
I understand sealed classes: the switch statement example provided makes sense to me. But, sealed interfaces are a mystery to me. Any class implementing an interface is forced to provide definitions for them. Interfaces don't compromise the integrity of the implementation because the interface is stateless on its own. Doesn't matter whether I wanted to limit implementation to a few selected classes.
Could you tell me the proper use case of sealed interfaces in Java 15+?
Basically to give a sealed hierarchy when there is no concrete state to share across the different members. That's the major difference between implementing an interface and extending a class - interfaces don't have fields or constructors of their own.
But in a way, that isn't the important question. The real issue is why you would want a sealed hierarchy to begin with. Once that is established it should be clearer where sealed interfaces fit in.
(apologies in advance for the contrived-ness of examples and the long winded-ness)
1. To use subclassing without "designing for subclassing".
Lets say you have a class like this, and it is in a library you already published.
public final class Airport {
private List<String> peopleBooked;
public Airport() {
this.peopleBooked = new ArrayList<>();
}
public void bookPerson(String name) {
this.peopleBooked.add(name);
}
public void bookPeople(String... names) {
for (String name : names) {
this.bookPerson(name);
}
}
public int peopleBooked() {
return this.peopleBooked.size();
}
}
Now, you want to add a new version to your library that will print out the names of people booked as they are booked. There are several possible paths to do this.
If you were designing from scratch, you could reasonably replace the Airport class with an Airport interface and design the PrintingAirport to compose with a BasicAirport like so.
public interface Airport {
void bookPerson(String name);
void bookPeople(String... names);
int peopleBooked();
}
public final class BasicAirport implements Airport {
private final List<String> peopleBooked;
public Airport() {
this.peopleBooked = new ArrayList<>();
}
#Override
public void bookPerson(String name) {
this.peopleBooked.add(name);
}
#Override
public void bookPeople(String... names) {
for (String name : names) {
this.bookPerson(name);
}
}
#Override
public int peopleBooked() {
return this.peopleBooked.size();
}
}
public final class PrintingAirport implements Airport {
private final Airport delegateTo;
public PrintingAirport(Airport delegateTo) {
this.delegateTo = delegateTo;
}
#Override
public void bookPerson(String name) {
System.out.println(name);
this.delegateTo.bookPerson(name);
}
#Override
public void bookPeople(String... names) {
for (String name : names) {
System.out.println(name);
}
this.delegateTo.bookPeople(names);
}
#Override
public int peopleBooked() {
return this.peopleBooked.size();
}
}
This isn't doable in our hypothetical though because the Airport class already exists. There are going to be calls to new Airport() and methods that expect something of type Airport specifically that can't be kept in a backwards compatible way unless we use inheritance.
So to do that pre-java 15 you would remove the final from your class and write the subclass.
public class Airport {
private List<String> peopleBooked;
public Airport() {
this.peopleBooked = new ArrayList<>();
}
public void bookPerson(String name) {
this.peopleBooked.add(name);
}
public void bookPeople(String... names) {
for (String name : names) {
this.bookPerson(name);
}
}
public int peopleBooked() {
return this.peopleBooked.size();
}
}
public final class PrintingAirport extends Airport {
#Override
public void bookPerson(String name) {
System.out.println(name);
super.bookPerson(name);
}
}
At which point we run into one of the most basic issues with inheritance - there are tons of ways to "break encapsulation". Because the bookPeople method in Airport happens to call this.bookPerson internally, our PrintingAirport class works as designed, because its new bookPerson method will end up being called once for every person.
But if the Airport class were changed to this,
public class Airport {
private List<String> peopleBooked;
public Airport() {
this.peopleBooked = new ArrayList<>();
}
public void bookPerson(String name) {
this.peopleBooked.add(name);
}
public void bookPeople(String... names) {
for (String name : names) {
this.peopleBooked.add(name);
}
}
public int peopleBooked() {
return this.peopleBooked.size();
}
}
then the PrintingAirport subclass won't behave correctly unless it also overrided bookPeople. Make the reverse change and it won't behave correctly unless it didn't override bookPeople.
This isn't the end of the world or anything, its just something that needs to be considered and documented - "how do you extend this class and what are you allowed to override", but when you have a public class open to extension anyone can extend it.
If you skip documenting how to subclass or don't document enough its easy to end up in a situation where code you don't control that uses your library or module can depend on a small detail of a superclass that you are now stuck with.
Sealed classes let you side step this by opening your superclass up to extension only for the classes you want to.
public sealed class Airport permits PrintingAirport {
// ...
}
And now you don't need to document anything to outside consumers, just yourself.
So how do interfaces fit in to this? Well, lets say you did think ahead and you have the system where you are adding features via composition.
public interface Airport {
// ...
}
public final class BasicAirport implements Airport {
// ...
}
public final class PrintingAirport implements Airport {
// ...
}
You might not be sure that you don't want to use inheritance later to save some duplication between the classes, but because your Airport interface is public you would need to make some intermediate abstract class or something similar.
You can be defensive and say "you know what, until I have a better idea of where I want this API to go I am going to be the only one able to make implementations of the interface".
public sealed interface Airport permits BasicAirport, PrintingAirport {
// ...
}
public final class BasicAirport implements Airport {
// ...
}
public final class PrintingAirport implements Airport {
// ...
}
2. To represent data "cases" that have different shapes.
Lets say you send a request to a web service and it is going to return one of two things in JSON.
{
"color": "red",
"scaryness": 10,
"boldness": 5
}
{
"color": "blue",
"favorite_god": "Poseidon"
}
Somewhat contrived, sure, but you can easily imagine a "type" field or similar that distinguishes what other fields will be present.
Because this is Java, we are going to want to map the raw untyped JSON representation into classes. Lets play out this situation.
One way is to have one class that contains all the possible fields and just have some be null depending.
public enum SillyColor {
RED, BLUE
}
public final class SillyResponse {
private final SillyColor color;
private final Integer scaryness;
private final Integer boldness;
private final String favoriteGod;
private SillyResponse(
SillyColor color,
Integer scaryness,
Integer boldness,
String favoriteGod
) {
this.color = color;
this.scaryness = scaryness;
this.boldness = boldness;
this.favoriteGod = favoriteGod;
}
public static SillyResponse red(int scaryness, int boldness) {
return new SillyResponse(SillyColor.RED, scaryness, boldness, null);
}
public static SillyResponse blue(String favoriteGod) {
return new SillyResponse(SillyColor.BLUE, null, null, favoriteGod);
}
// accessors, toString, equals, hashCode
}
While this technically works in that it does contain all the data, there isn't all that much gained in terms of type-level safety. Any code that gets a SillyResponse needs to know to check the color itself before accessing any other properties of the object and it needs to know which ones are safe to get.
We can at least make the color an enum instead of a string so that code shouldn't need to handle any other colors, but its still far less than ideal. It gets even worse the more complicated or more numerous the different cases become.
What we ideally want to do is have some common supertype to all the cases that you can switch on.
Because its no longer going to be needed to switch on, the color property won't be strictly necessary but depending on personal taste you can keep that as something accessible on the interface.
public interface SillyResponse {
SillyColor color();
}
Now the two subclasses will have different sets of methods, and code that gets either one can use instanceof to figure out which they have.
public final class Red implements SillyResponse {
private final int scaryness;
private final int boldness;
#Override
public SillyColor color() {
return SillyColor.RED;
}
// constructor, accessors, toString, equals, hashCode
}
public final class Blue implements SillyResponse {
private final String favoriteGod;
#Override
public SillyColor color() {
return SillyColor.BLUE;
}
// constructor, accessors, toString, equals, hashCode
}
The issue is that, because SillyResponse is a public interface, anyone can implement it and Red and Blue aren't necessarily the only subclasses that can exist.
if (resp instanceof Red) {
// ... access things only on red ...
}
else if (resp instanceof Blue) {
// ... access things only on blue ...
}
else {
throw new RuntimeException("oh no");
}
Which means this "oh no" case can always happen.
An aside: Before java 15 to remedy this people used the "type safe visitor" pattern. I recommend not learning that for your sanity, but if you are curious you can look at code ANTLR generates - its all a large hierarchy of differently "shaped" data structures.
Sealed classes let you say "hey, these are the only cases that matter."
public sealed interface SillyResponse permits Red, Blue {
SillyColor color();
}
And even if the cases share zero methods, the interface can function just as well as a "marker type", and still give you a type to write when you expect one of the cases.
public sealed interface SillyResponse permits Red, Blue {
}
At which point you might start to see the resemblance to enums.
public enum Color { Red, Blue }
enums say "these two instances are the only two possibilities." They can have some methods and fields to them.
public enum Color {
Red("red"),
Blue("blue");
private final String name;
private Color(String name) {
this.name = name;
}
public String name() {
return this.name;
}
}
But all instances need to have the same methods and the same fields and those values need to be constants. In a sealed hierarchy you get the same "these are the only two cases" guarantee, but the different cases can have non-constant data and different data from each other - if that makes sense.
The whole pattern of "sealed interface + 2 or more record classes" is fairly close to what is intended by constructs like rust's enums.
This also applies equally to general objects that have different "shapes" of behaviors, but they don't get their own bullet point.
3. To force an invariant
There are some invariants, like immutability, that are impossible to guarantee if you allow subclasses.
// All apples should be immutable!
public interface Apple {
String color();
}
public class GrannySmith implements Apple {
public String color; // granny, no!
public String color() {
return this.color;
}
}
And those invariants might be relied upon later on in the code, like when giving an object to another thread or similar. Making the hierarchy sealed means you can document and guarantee stronger invariants than if you allowed arbitrary subclassing.
To cap off
Sealed interfaces more or less serve the same purpose as sealed classes, you just only use concrete inheritance when you want to share implementation between classes that goes beyond what something like default methods can give.
Although interfaces have no state themselves, they have access to state, eg via getters, and may have code that does something with that state via default methods.
Therefore the reasoning supporting sealed for classes may also be applied to interfaces.
Suppose you write an authentication library, containing an interface for password encoding, ie char[] encryptPassword(char[] pw). Your library provides a couple of implementations the user can choose from.
You don't want him to be able to pass in his own implementation that might be insecure.
Could you tell me the proper use case of sealed interfaces in Java
15+?
I wrote some experimental code and a supporting blog to illustrate how sealed interfaces could be used to implement an ImmutableCollection interface hierarchy for Java that provides contractual, structural and verifiable immutability. I think this could be a practical use case for sealed interfaces.
The example includes four sealed interfaces: ImmutableCollection, ImmutableSet, ImmutableList and ImmutableBag. ImmutableCollection is extended by ImmutableList/Set/Bag. Each of the leaf interfaces permits two final concrete implementations. This blog describes the design goal of restricting the interfaces so developers cannot implement "Immutable" interfaces and provide implementations that are mutable.
Note: I am a committer for Eclipse Collections.
Interfaces are not always entirely defined by their API alone. Take, for example ProtocolFamily. This interface would be easy to implement, considering its methods, but the result would not be useful regarding the intended semantics, as all methods accepting ProtocolFamily as input would just throw UnsupportedOperationException, in the best case.
This is a typical example for an interface that would be sealed if that feature existed in earlier versions; the interface is intended to abstract the implementations exported by a library, but not to have implementations outside that library.
The newer type ConstantDesc mentions that intention even explicitly:
Non-platform classes should not implement ConstantDesc directly. Instead, they should extend DynamicConstantDesc…
API Note:
In the future, if the Java language permits, ConstantDesc may become a sealed interface, which would prohibit subclassing except by explicitly permitted types.
Regarding possible use cases, there is no difference between a sealed abstract class and a sealed interface, but the sealed interface still allows implementors extending different classes (within the limits set by the author). Or being implemented by enum types.
In short, sometimes, interfaces are used to have the least coupling between a library and its clients, without the intention of having client-side implementations of it.
Since Java introduced records in version 14, one use case for sealed interfaces will certainly be to create sealed records. This is not possible with sealed classes, because records cannot extend a class (much like enums).
Before java 15 developers used to think in a way that code reusability is the goal. But it's not true to all extents, in some cases we want wide accessibility but not extensibility for better security and also codebase management.
This feature is about enabling more fine-grained inheritance control in Java. Sealing allows classes and interfaces to define their permitted subtypes.
The sealed interface allows us to enable it to reason clearly all the classes that can implement it.

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.

Understanding Abstract Factory pattern

I've read about abstract factory patter on wiki. But I don't understand really profit by using this pattern. Can you get an example in which is hard to avoid abstract factory pattern. Consider the following Java code:
public abstract class FinancialToolsFactory {
public abstract TaxProcessor createTaxProcessor();
public abstract ShipFeeProcessor createShipFeeProcessor();
}
public abstract class ShipFeeProcessor {
abstract void calculateShipFee(Order order);
}
public abstract class TaxProcessor {
abstract void calculateTaxes(Order order);
}
// Factories
public class CanadaFinancialToolsFactory extends FinancialToolsFactory {
public TaxProcessor createTaxProcessor() {
return new CanadaTaxProcessor();
}
public ShipFeeProcessor createShipFeeProcessor() {
return new CanadaShipFeeProcessor();
}
}
public class EuropeFinancialToolsFactory extends FinancialToolsFactory {
public TaxProcessor createTaxProcessor() {
return new EuropeTaxProcessor();
}
public ShipFeeProcessor createShipFeeProcessor() {
return new EuropeShipFeeProcessor();
}
}
// Products
public class EuropeShipFeeProcessor extends ShipFeeProcessor {
public void calculateShipFee(Order order) {
// insert here Europe specific ship fee calculation
}
}
public class CanadaShipFeeProcessor extends ShipFeeProcessor {
public void calculateShipFee(Order order) {
// insert here Canada specific ship fee calculation
}
}
public class EuropeTaxProcessor extends TaxProcessor {
public void calculateTaxes(Order order) {
// insert here Europe specific tax calculation
}
}
public class CanadaTaxProcessor extends TaxProcessor {
public void calculateTaxes(Order order) {
// insert here Canada specific tax calculation
}
}
If we need to just create objects in a code below 1-2 times in a code then we can use just new operator. And why we need in abstract factory?
You are missing half of the work :)
void processOrder(FinancialToolsFactory ftf,Order o) {
tft.createTaxProcessor().calculateTaxes(o);
tft.createShipFeeProcessor().calculateShipFee(o);
}
this code works as well as you pass a canadian or european implementation of FinancialToolsFactory (you can externalize the implementor class to external resource and instantiate with a Class.newInstance(), for example).
In this case one of the real benefits of pattern usage is not writing the code that implements the pattern, but who use that code!
PS: My answer is intentionally incomplete and try to answer just this specific question; a discussion about pattern and their benefits is too big!
You'd take advantage of this pattern if you were to support different implementations transparently. By delegating the decision of which implementation to use to the factory, you have a single point in your code where that decision is made (a.k.a. single responsibility).
The abstract factory pattern takes this concept beyond by aggregating related factories, such as different financial tools factories in your sample.
Now, if you only instantiate your financial tools once or twice in your code, using factories is over-engineering. The gain comes when you need to instantiate different implementations of the same interfaces in different places many times and you want to be able to work without worrying about which implementation you are using or how that decision is made.
There are quite some resources about this pattern on the web, and it's hard to guess what might be the best way of explaining its purpose in a way that sounds "plausible" for you.
But I think that the key point is:
With this pattern, someone who wants to create an instance of a particular implementation of an interface does not need to know what this particular implementation is. The call to the new operator is hidden inside the factory, and the user of the factory does not need to know the concrete class.
This makes it easier to switch the implementation later: You don't have to find and adjust all places where new ConcreteClass() was called and change it to new OtherConcreteClass() in order to use a different implementation. You just pass a different factory around, and everybody who uses this factory automatically creates instances of OtherConcreteClass (without even knowing that he does so...)

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()));

Categories

Resources