Design pattern to set certain fields in object based on enum values - java

So basically what I want to do is fill/not fill certain fields in an object based off a list of enums.
For example the object in question:
case class Car(brand: String,
model: String,
wheels: Int,
airbags: Boolean,
seats: Int,
cruiseControl: Boolean,
photo: String,
parkingAssist: Boolean)
This is the full object, and depending on list of Java enum types I want to set certain fields. Also combinations are possible and they might overlap.
enum CarType {
BASIC_CAR,
LUXURY_CAR,
SAFE_CAR,
PICTURE_CAR
}
So basically depending on the CarType I would like to set certain fields of Car. For example:
BASIC_CAR need to se brand, model, wheels and seats.
LUXURY_CAR need to set brand, model, cruiseControl and parkingAssist
SAFE_CAR need to set airbags
PICTURE_CAR need to set parkingAssist
So I will receive a list of these enums and then need to create the object. For example I will have one object with BASIC_CAR, LUXURY_CAR, SAFE_CAR which means the object I create will have to have all fields except parkingAssist.
So in the end, the enums relate to certain field and basically on the (combination of) enums I require to set certain fields in the object. What would be a good design for this?

I think you should use the Decorator pattern to solve this problem.
Check out this web site to get an example:
https://sourcemaking.com/design_patterns/decorator
I edit my post for being more specific, I mean something like this:
public interface Car {
public void assemble();
}
public class BasicCar implements Car {
#Override
public void assemble() {
//set basic car: brand, model, wheels and seats.
}
}
public class CarDecorator implements Car {
protected Car car;
public CarDecorator(Car c){
this.car=c;
}
#Override
public void assemble() {
this.car.assemble();
}
}
public class LuxuryCar extends CarDecorator {
public LuxuryCar(Car c) {
super(c);
}
#Override
public void assemble(){
super.assemble();
//add especial fields for luxury car or override values from basic car
}
}
and depending on the Enum value you can instanciate different classes: new LuxuryCar(), new SportCar()

Related

How we can remove code redundancy/ improve code by using generics/ any other way [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
An example of my problem is shown below. Both classes Car and Bike have the same fields (wheel and bodyColor).
In class AssembleVehicle, the method getDetails is almost duplicated for Car and Bike. Is there any way to remove redundancy or improve coding standards?
class Vehicle {
Car car;
Bike bike;
//setter & getter
}
class Car {
String wheel;
String bodyColor;
//setter & getter
}
class Bike {
String wheel;
String bodyColor;
//setter & getter
}
class AssembleVehicle {
public void init(Vehicle v) {
getDetails(v.getCar);
getDetails(v.getBike);
}
private void getDetails(Car c) {
String wheel = c.wheel;
String bodyColor = c.bodyColor;
}
private void getDetails(Bike c) {
String wheel = c.wheel;
String bodyColor = c.bodyColor;
}
}
Here, how we can remove code redundancy for getDetails?. Can we use this method only once?
What I understand about generics is: generics allow you to customize a "generic" method or class to whatever type you're working with. For example, suppose you have a method that adds two numbers together. In order to work with the types themselves, you might have to create multiple versions of this method.
Thinking about OOP in this way places the wrong emphasis. Even if you fix your initial mishap of having a Vehicle with a car and a bike inside of it, the 'improved' model of the Vehicle superclass with the wheel and bodyColor fields is probably broken (depending on the actual domain you are working in). For instance bike wheels and car wheels are very different, and a sleigh is a vehicle without any wheels. Things that look similar at first glance are not always good candidates to pull up into a super class.
The problem is that we are tempted to assume that if two examples of a category share some common traits, that these traits are present for all the members of this category (BTW this tendency to generalize might also be the cause of many problems in society).
The power of OOP does not come from extracting super classes like the Vehicle and 're-using' some fields. Direct subclassing is a very drastic measure that should not be applied lightly, because it means all present and future subclasses MUST inherit the complete contract (data and behavior) of the super class. As soon as you want to add a new subclass and are forced to make exceptions you know the model is wrong. And at that point changing it will impact all the existing sub classes. In fact, direct subclassing is nearly always a violation of the open-closed principle, the second in the set of SOLID design principles.
A much more flexible approach is to extract interfaces to encapsulate certain aspects of a category of classes:
interface Wheeled {
String getWheels();
}
class Car implements Wheeled {
private String wheels;
#Override
public String getWheels() {
return wheels;
}
}
class Bike implements Wheeled {
private String wheels;
#Override
public String getWheels() {
return wheels;
}
}
This would allow treating Cars and Bikes the same, if you are only interested in wheels:
List<Wheeled> wheeledVehicles = new ArrayList<>();
wheeledVehicles.add(new Car());
wheeledVehicles.add(new Bike());
String firstWheels = wheeledVehicles.get(0).getWheels());
If you are interested in body color, or even wheels AND body color, you are free to play with interfaces:
interface Wheeled {
String getWheels();
}
interface Coloured{
String getBodyColour();
}
interface WheeledAndColoured extends Wheeled, Coloured {}
Which allows:
List<WheeledAndColoured> wheeledAndColouredVehicles = new ArrayList<>();
wheeledAndColouredVehicles.add(new Car());
wheeledAndColouredVehicles.add(new Bike());
WheeledAndColoured first = wheeledAndColouredVehicles.get(0);
String firstWheels = first.getWheels());
String firstColour = first.getBodyColour());
If you really want to, you can extract the wheels field into a super class, but the immediate gain is limited. Private fields are an implementation detail, and pulling them into a super class is certainly not the type of re-use that will make a big difference. At the same time, it would create a very strong dependency between those classes and make future changes harder.
Maybe if you need to implement some 'complex' shared logic related to wheels, it is time to create the Wheels class:
class Wheels {
private String type;
private int number;
private BigDecimal price;
public BigDecimal getReplacementCosts() {
return price.multiply(BigDecimal.valueOf(number));
}
}
Now the Car class can collaborate with the Wheels class as one of its fields:
class Car implements Wheeled {
private Wheels wheels;
#Override
public String getWheels() {
return wheels.getType();
}
public BigDecimal getMaintenanceCosts() {
return wheels.getReplacementCosts();
}
}
Notice that, because we didn't tie in Car and Bike with a common super class, we are not forced to change either the Wheeled interface, nor the Bike class. If you want to add the Wheels logic to Bike then you can easily do so, but you are not forced to. You would be, if the wheels fields was in the shared super class Vehicle.
So the motto is: Favor collaboration over extension because it's way more flexible.
I agree with other commenters that the Vehicle class does not really make sense. I recommend following their advice and having Car and Bike extend the Vehicle class. This is better than using generics, because you can "guarantee" that you cannot use AssembleVehicle with classes that aren't vehicles and don't meet the requirements of having a wheel and a bodyColour.
However, if you still want to use generics, here is how you can use them:
class Car {
String wheel;
String bodyColor;
//setter & getter
}
class Bike {
String wheel;
String bodyColor;
//setter & getter
}
class AssembleVehicle <T> {
public void init(T vehicle) {
getDetails(vehicle);
}
private void getDetails(T vehicle) {
String wheel = vehicle.wheel;
String bodyColor = vehicle.bodyColor;
}
}
This allows you to write the getDetails method only once.

Problem with generic class and class Type

I have created a (generic) class Store, which I use to get 3 stores(smithy, jeweler and bookstore). The store is basically just an ArrayList, which holds different objects, that can be bought in each store. Now I want to limit the smithy to only hold weapons, the jeweler to only hold rings, etc.
I tried realizing that like this:
Store<Weapon> smithy = new Store<>();
Store<Ring> jeweler = new Store<>();
Store<Scroll> bookstore = new Store<>();
However do I get an error later on in the code, because the method only accepts the type(Object, Store<Object>) and not (Object,Store<Weapon>). But the Weapon class is a subclass of my Object class, so I don't understand why this is a problem.
My Store class:
public class Store <T extends Object>{
/...
}
My Object Class:
public class Object {
//Konstruktor
public Object() {
}
}
My Weapon class :
public class Weapon extends Object {
//Konstruktor
public Weapon () {
super();
};
The piece of code I get the problem in:
this.myPlayer.buy(this.smithy.getItemAt(itemNr), this.smithy);
The buy method:
public void buy(Object obj, Store<Object> store){
//...}
the error:
the method buy(Object,Store<Object>) in the type Player is not applicable for the arguments (Object, Store<Weapon>)
Since I have three different stores with each their own kind of Objects(Weapon, Ring, Scroll) I cannot just change the buy method to (Object, Store<Weapon>). And writing three methods for each store seems a bit much to me.
I appreciate your helping.

Using variables for creating objects and calling methods in Java

Hi Everyone I am beginner in java and came across a question like Can I use variables for creating objects and calling methods to reuse the code.
Tesla.java
public class Tesla extends Car {
#Override
public void buy(){
System.out.println("Tesla bought");
}
#Override
public void sell(){
System.out.println("Tesla Sold");
}
}
Ford.java
public class Ford extends Car {
#Override
public void buy(){
System.out.println("Ford bought");
}
#Override
public void sell(){
System.out.println("Ford Sold");
}
}
Car.java
public class Car {
public static void main(String[] args) {
String[][] arr = {{"Tesla, Buy"},{"Ford", "Sell"},{"Benz", "Sell"}};
Car car = new Tesla();
car.buy();
Car car = new Ford();
car.sell();
}
public void buy() {
System.out.println("Car bought");
}
public void sell() {
System.out.println("Car Sold");
}
}
Here instead of creating each object I just want to use one for loop and create respective object and respective method based on the array elements.
Logic like below.
public static void main(String[] args) {
String[][] arr = {{"Tesla, Buy"},{"Ford", "Sell"},{"Benz", "Sell"}};
for(int i = 0;i<arr.length-1;i++){
Car car = new arr[i][0]();
car.arr[i][1];
}
}
How to achieve above logic? Is this something achievable in Java? I searched in google couldn't find relevant questions or problems. Please help me. Thanks in advance.
Note:- I don't want a workaround I just want to know the if logic is achievable using any advanced java concepts I am unaware of.
If you want to instantiate objects of various subclasses according to string inputs, you have at least two options:
Reflection
Builder pattern
Reflection
As commented by Nikolaus, one route is to use Java’s reflection facility. This is the “magic” way, where you would find at runtime the name of the class matching your string input. For example, "Tesla" string would lead you to loading an object of type Class representing the Tesla class you wrote at compile time. You would call methods on that Class object to create an instance of your subclass. In other words, you are programmatically doing a roundabout replacement for the code new Tesla(…).
I do not recommend going the reflection route. This is not “normal” Java app programming. Reflection is usually done only in certain kinds of frameworks and in special rare circumstances.
Builder pattern
The other route more commonly used is the Builder pattern. You define another class called something like CarBuilder. You pass your text values into one or more methods of an object of this type CarBuilder. Those methods validate the inputs.
When done setting up the various pieces of input, you eventually call a method conventionally called build. That method produces and returns an object of type Car. That Car object is actually from a subclass, is actually a Tesla or Ford.
CarBuilder builder = new CarBuilder() ;
builder.setBrand( "Tesla" ) ;
builder.set… = … ;
…
Car car = builder.build() ; // Actually a `Tesla` subclass object.
Rather than create different classes (Tesla, Ford) that inherit from a superclass (Car), just pass in parameters to your Car class methods:
public class Car {
public void Buy(String brand) {
System.out.println(brand+" bought");
}
public void Sell(String brand) {
System.out.println(brand+" Sold");
}
}
I would also move the main method out to a separate Runner class. Its only responsibility would be to run the program and nothing else. That way you decouple the classes that implement your model (Car...) from the classes used to run the program.
Additionally, my example is a bit weak in the sense that I have to pass in the brand for each method. What you should do instead is introduce the notion of a constructor in your Car class and the notion of a class attribute. Your code then becomes
public Class Car{
private String brand;
public Car(String brand){
this.brand = brand;
}
public void Buy(String brand) {
System.out.println(brand+" bought");
}
public void Sell(String brand) {
System.out.println(brand+" Sold");
}
}
One last thing: methods typically don't start with a capital letter in Java so you should rename Buy and Sell to buy and sell.
Your second requirement is also to parameterize the action (buy or sell). You can apply the same principle i.e. have a generic method (doAction()) that will now take in 2 parameters: the car brand and the action you want to do. But IMHO that's pushing it too far and losing value.

Multiple implementations of common interface

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));
}
...
}

How to enforce two classes to have the same certain set of variables without inheritance, with annotations?

I have classes Productand ProductImage
I want them both to have the following set of booleans: toBeSynced, toBeAdded and toBeDeleted
How can I enforce that using some OOP Design pattern? I thought of interfaces but those are for meethods. I dont want them to extend a Syncable class because it doesnt feel right. I dont want to manually add those booleans to both classes, I want the booleans to come from somewhere else.
EDIT: I understood that this can be achieved by annotations. How would that work?
You may use composition if you want:
class Sync {
boolean toBeSynced, toBeAdded ,toBeDeleted
}
class Product {
Sync sync;
}
class ProductImage {
Sync sync;
}
You can use composition to "mixin" the values that you want.
For example, we can have a class called Syncable, which has the values you want.
public class Syncable
{
// instance variables - replace the example below with your own
private boolean toBeSynced;
public void setToBeSynced(boolean toBeSynced){
this.toBeSynced = toBeSynced;
}
public boolean getToBeSynced(){
return this.toBeSynced;
}
}
Then, in your product class for example
public class Product
{
Syncable sync;
public Product()
{
sync = new Syncable();
}
}
After doing this, you can modify the boolean values as you wish.
public static void main(String[] args){
Product p = new Product();
p.sync.setToBeSynced(false);
System.out.println(p.sync.getToBeSynced());
}
Of course, you may wish to add another layer of abstraction with methods in the product class that can set and get the boolean values that you want.
For example, you could add the following 2 methods to the product class:
public void setBoolean(boolean bool){
this.sync.setToBeSynced(bool);
}
public boolean getBoolean(){
return this.sync.getToBeSynced();
}
Then, in another part of your program, you could state
Product p = new Product();
p.setBoolean(true);
boolean bool = p.getBoolean();
The best way is through inheritance, by using an abstract class to define the common properties.
if it does not feel right, your naming and/or design is probably incorrect
abstract class Syncable {
boolean toBeSynced;
boolean toBeAdded;
boolean toBeDeleted;
abstract void sync();
abstract void add();
abstract void delete();
}
Product:
class Product extends Syncable {
// impl...
}
ProductImage:
class ProductImage extends Syncable {
// impl...
}
EDIT:
You should really think about what your classes are going to do, i.e is-a (inheritance) vs has-a (composition) relationships, for example:
is a Product a Syncable versus does a Product have a Sync object;
in the same way you would think of a Car, does a car have wheels, or is it a wheel? i think not ;)

Categories

Resources