Consider the following: say we have an IRestaurant and an IBooking interface.
We then have the following interface function:
interface IBooking {
void reserve(IRestaurant restaurant);
}
However, business requirements dictate a booking service in a country could make reservations to only restaurants in the same country. Then say we have in USA:
class USABooking implements IBooking { ... }
class USARestaurant implements IRestaurant { ... }
In this case, since reserve() in IBooking takes in any instance of IRestaurant, the USABooking implementation would be required to check the instance of the IRestaurant to see if it is an instance of a USARestaurant and then downcast. However, we could also do this as an alternative:
interface IBooking<R extends IRestaurant> {
void reserve(R restaurant);
}
class USABooking implements IBooking<USARestaurant> {
void reserve(USARestaurant restaurant) { ... }
}
Is this a recommended way to go about enforcing the type limitation? In other words, is this better than performing runtime checks on the restaurant instance types? The typing approach sounds good to me, but I just want to make sure it won't "blow up" the architecture and turn out to be a misuse or abuse, since there are other interfaces that also would require such limitations (e.g. ICuisine).
Here's another alternative since I don't understand why there are USABooking and USARestaurant classes:
Consider just having a Booking and Restaurant class, where Restaurant provides a getCountry() method. Separately, to avoid a proliferation of classes, a Booking instance might have something like a List<RestaurantBookingRule> - in this case there would be a single rule that checks the country of the Restaurant. For example:
public class Restaurant {
private final String country; // constructor omitted
public String getCountry() { return country; }
}
public interface RestaurantBookingRule {
public void validateRequest(Restaurant r); // throws exception if the rule is broken
}
public class RequiredCountry implements BookingRule {
private final String country; // constructor omitted
public void validateRequest(Restaurant r) {
if (!r.getCountry().equals(country))
throw ...
}
}
public class Booking {
private final List<RestaurantBookingRule> rules; // constructor omitted
public void reserve(Restaurant r) {
rules.forEach(r -> r.validateRequest(r));
...
}
}
then:
Restaurant r1 = new Restaurant("USA");
Restaurant r2 = new Restaurant("CAN");
Booking usaBooking = new Booking(List.of(new RequriedCountry("USA"));
usaBooking.reserve(r1); // ok
usaBooking.reserve(r2); // throws exception
Related
I have entity in database, say, MonthPlan:
class MonthPlan {
private boolean approved;
// other fields
}
There is also REST interface, which accepts external requests based on which program changes entity instances. For example, request
class EditMonthPlanRequest {
private long amount;
// other fields
}
is used to change month plan amount.
What I need is to execute different actions on MonthPlan entity based on value of approved field. For example, code for mentioned request could be as following
MonthPlan plan = getPlan(...);
if (plan.isApproved()) {
// actions using data from EditMonthPlanRequest
} else {
// other actions using data from EditMonthPlanRequest
}
There would be 5-6 different requests each with exactly two variants of actions based on value of approved field of edited entity. What OOP design pattern can I use for such use case to write more concise code?
I do not think you need a design pattern in such a simple case. Each request will be processed by the corresponding method at Service layer.
In this scenario, the state pattern is more suitable.
State design pattern is used when an Object changes its behavior based on its internal state.
If we have to change behavior of an object based on its state, we can have a state variable in the Object and use if-else condition block to perform different actions based on the state. State pattern is used to provide a systematic and lose-coupled way to achieve this through Context and State implementations.
Try to implement based on your description:
public class StatePattern {
public static void main(String[] args) {
MonthPlan monthPlan = null; //= new MonthPlan(...)
StateContext stateContext = new StateContext();
if(monthPlan.isApproved()) {
stateContext.setState(new Approved());
}else {
stateContext.setState(new NotApproved());
}
}
}
class MonthPlan {
private boolean approved;
public boolean isApproved() {
return approved;
}
// other fields
}
interface State{
public void doAction(StateContext ctx);
}
class StateContext{
private State currentState;
public StateContext() {
//default Approved state, you can change if you want
currentState = new Approved();
}
public void setState(State state) {
currentState = state;
}
public void doAction() {
currentState.doAction(this);
}
}
class Approved implements State{
#Override
public void doAction(StateContext ctx) {
//actions using data from EditMonthPlanRequest
}
}
class NotApproved implements State{
#Override
public void doAction(StateContext ctx) {
//other actions using data from EditMonthPlanRequest
}
}
For this simple case, the Template Method pattern may apply:
abstract class AbstractRequest {
public void execute(...){
MonthPlan plan = getPlan(...);
if (plan.isApproved()) {
executeForApproved(plan);
} else {
executeForNonApproved(plan);
}
}
protected abstract void executeForApproved(MonthPlan plan);
protected abstract void executeForNonApproved(MonthPlan plan);
}
This way, you don't need to repeat the if statement and the getPlan(...) in each subclass:
class EditMonthPlanRequest extends AbstractRequest {
private long amount;
// other fields
protected void executeForApproved(MonthPlan plan){
...
}
protected void executeForNonApproved(MonthPlan plan){
...
}
}
If you want to do OOP, then replace conditionals with polymorphism.
In this example, it means splitting MonthPlan in two.
class ApprovedMonthPlan extends MonthPlan
class UnapprovedMonthPlan extends MonthPlan
Each class handles EditMonthPlanRequest in its own way.
I had an interview yesterday and had asked an OOD question:
Race-Car Store System:
The system stores information about cars available for players.
Two types of gear changing strategies: manual/automatic.
Two types of fuel: gasoline/diesel.
Design a system that can produce cars requested by players (If the
player wants a car with manual gear changing and burn diesel, your
system should provide one instance of the car meets the requirements).
The system should have good scalability and maintainability.
My thoughts and solution:
My thought is the requirement contains two attributes: gear and fuel. I plan to make an abstract class contains the attributes and corresponding behaviors. Considering scalability would have an interface Movable which contains behaviors what a car can do.
If any new attribute is added in the future, either create a new abstract class contains the new attribute or add the attribute into the existing abstract class, if there's new behaviors are required, I would either create new interface or add the behavior into existing interface.
Here's what I have done:
An interface contains general behaviors, currently has showSpecs() only.
public interface Movable {
public String showSpecs();
}
An abstract class contains attributes fuel and gear
public abstract class Car implements Movable {
String gear;
String fuel;
abstract void setFuel(String fuel);
abstract String getFuel();
abstract void setGear(String gear);
abstract String getGear();
}
Now the race car class implementaion:
public class RaceCar extends Car {
public RaceCar(String fuel, String gear) {
this.fuel = fuel;
this.gear = gear;
}
public void setFuel(String fuel) {
this.fuel = fuel;
}
public String getFuel() {
return this.fuel;
}
public void setGear(String gear) {
this.gear = gear;
}
public String getGear() {
return this.gear;
}
public String showSpecs() {
StringBuilder sb = new StringBuilder();
sb.append("Gear:").append(this.gear);
sb.append("Fuel:").append(this.fuel);
return sb.toString();
}
}
Below is the main class I have:
public class Main {
public static void main(String[] args) {
System.out.println("get started...");
Car car = new RaceCar("diseal", "automatic");
System.out.println(car.showSpecs());
}
}
The interviewer replied that the solution I provided is not scalable and hard to maintain but didn't provide details so I am still confused about what mistakes I made and how to improve it.
Can anyone help share your thoughts and point out what am I supposed to improve?
Thanks!
I would have answered this question with 2 classes, Car and CarBuilder:
public final class Car {
private final Fuel fuel;
private final Gears gears;
public Car(Fuel fuel, Gears gears) {
this.fuel = fuel;
this.gears = gears;
}
public Fuel getFuel() {
return fuel;
}
public Gears getGears() {
return gears;
}
enum Fuel {
GASOLINE,
DEISEL
}
enum Gears {
AUTOMATIC,
MANUAL
}
}
public class CarBuilder {
//sensible defaults:
private Car.Fuel fuel = Car.Fuel.GASOLINE;
private Car.Gears gears = Car.Gears.MANUAL;
public CarBuilder() {
}
public CarBuilder withFuelType(Car.Fuel fuel) {
this.fuel = fuel;
return this;
}
public CarBuilder withGearBox(Car.Gears gears) {
this.gears = gears;
return this;
}
public Car build() {
return new Car(this.fuel, this.gears);
}
}
Scalability and maintainability is achieved by the fact that these are the only 2 classes that need to be changed in the future, should requirements change. Car is immutable and also contains the enums required to represent its internal state, so these attributes can't leak out of the context/object in which they make sense so make it easier to maintain in the future.
The builder class, while basic in its current form, can be extended to accommodate more complex construction requirements without leaking implementation details into the Car class.
The default values are optional, but might make sense.
A car can be constructed as such:
//Default car:
Car car = new CarBuilder().build();
//Customised car:
Car car = new CarBuilder().withFuelType(Car.Fuel.DEISEL).withGearBox(Car.Gears.AUTOMATIC).build();
I thought that maybe he was expecting something like pluggable classes when he mentioned scalable and maintainable. So I think maybe this strategy pattern was expected. If transmission or injection is expected to do some real logic, I can assume them as behaviors instead of just state. Thus results with this implementation.
public interface TransmissionPolicy {
public void transmit();
}
public class AutomaticTransmission implements TransmissionPolicy {
public void transmit() {
//do some real logic here
print("automatic...");
}
}
public class ManualTransmission implements TransmissionPolicy {
public void transmit() {
print("we love it..."); //just an example of really simple logic
}
}
public interface InjectionPolicy {
public void inject();
}
public class DieselInjection implements InjectionPolicy {
public void inject() {
print("diesel");
}
}
public class GasolineInjection implements InjectionPolicy {
public void inject() {
print("gasoline...");
}
}
public class Car {
public void make(TransmissionPolicy transmission, InjectionPolicy injection) {
//set other parts
transmission.transmit();
//set other parts
injection.inject();
//other parts
}
}
//--------------somewhere in some clients client --------------------
Car car = new Car();
//actually, to be really configurable use a factory method here.
car.make(new ManualTransmission(), new GasolineInjection());
If that was expected then with just lambdas or command pattern it would be made also.
Firstly, I believe my question is badly worded but don't really understand how to phrase it.
I have a starting interface that is being implemented by a number of classes. What I want to do is to see if there is a way to create a new object such that I am being passed the generic interface, then based on the method .getClass().getSimpleName(), create a new object based on that string.
Is the only way to create a switch case statement? As the number of implementing classes are too many (about 100 or so).
Reference code:
public interface MyInterface {
public void someMethod();
}
then I would have my implementing classes:
public class MyClass1 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass2 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass3 implements MyInterface {
public void someMethod() { //statements }
}
What I want to have in the end is another class which is passed an argument of type MyInterface, get the simple name from that and create a new instance of MyClassX based on that simple name.
public class AnotherClass {
public void someMethod(MyInterface interface) {
if (interface == null) {
System.err.println("Invalid reference!");
System.exit(-1);
} else {
String interfaceName = interface.getClass().getSimpleName();
/**
* This is where my problem is!
*/
MyInterface newInterface = new <interfaceName> // where interfaceName would be MyClass1 or 2 or 3...
}
}
}
Any help is highly appreciated!
You can use reflection for this:
public void someMethod(MyInterface myInterface) {
Class<MyInterface> cl = myInterface.getClass();
MyInteface realImplementationObject = cl.newInstance(); // handle exceptions in try/catch block
}
This is a common problem with many solutions. When I face it, I never use reflection because it is difficult to maintain if it is part of a big project.
Typically this problem comes when you have to build an object based on a user selection. You can try a Decorator pattern for that. So, instead of building a different object for each option. You can build a single object adding functionality depending on a selection. For instance:
// you have
Pizza defaultPizza = new BoringPizza();
// user add some ingredients
Pizza commonPizza = new WithCheese(defaultPizza);
// more interesting pizza
Pizza myFavorite = new WithMushroom(commonPizza);
// and so on ...
// then, when the user checks the ingredients, he will see what he ordered:
pizza.ingredients();
// this should show cheese, mushroom, etc.
under the hood:
class WithMushroom implements Pizza {
private final Pizza decorated;
public WithMushroom(Pizza decorated) {
this.decorated = decorated;
}
#Override
public Lizt<String> ingredients() {
List<String> pizzaIngredients = this.decorated.ingredients();
// add the new ingredient
pizzaIngredients.add("Mushroom");
// return the ingredients with the new one
return pizzaIngredients;
}
}
The point is that you are not creating an object for each option. Instead, you create a single object with the required functionality. And each decorator encapsulates a single functionality.
At my work, we have surveys, and one survey involves multiple steps. I work in automation, so I design tests around the page-objects we create for these surveys. We call this particular survey a "flow" survey because it has multiple steps. So you can skip step1 (survey A), then complete or skip step 2 (survey B), then complete or skip step 3 (survey C). Naively, we could write a test that just has methods that look like this:
public void completeSurveyA() {
//...
}
public void skipSurveyB() {
//...
}
public void completeSurveyB() {
//...
}
public void skipSurveyC() {
//...
}
public void completeSurveyC() {
//...
}
You would use it like this
completeSurveyA();
skipSurveyB();
completeSurveyC();
However, that could be a problem because we might call completeSurveyB() before we call completeSurveyA(), call completeSurveyA twice, etc. and the test would break. To avoid this, I introduced a different approach where calling a method on surveyA would return a surveyB object, which would return a surveyC object.
public class SurveyFlow() {
public SurveyB completeSurveyA() {
//...
return new SurveyB();
}
private class SurveyB() {
public SurveyC skipSurveyB() {
//...
return new SurveyC();
}
public SurveyC completeSurveyB() {
//...
return new SurveyC();
}
private class SurveyC() {
public void skipSurveyC() {
//...
}
public void completeSurveyC() {
//...
}
}
}
}
You would use it like this
new SurveyFlow().completeSurveyA().skipSurveryB().completeSurveyC();
The pattern reminds me of a state machine because only certain methods are available to you in different states, but I'm wondering if there is a more specific name for this pattern.
According to the classes of your example, it's a FluentInterface:
Probably the most important thing to notice about this style is that the intent is to do something along the lines of an internal DomainSpecificLanguage. (...) The API is primarily designed to be readable and to flow.
It's not the builder pattern, because you're not building anything (i.e. you don't have a final build() method where data gathered in previous steps is used to create an instance).
It's not the state pattern either, because operations (skip() and complete() in this case) do not depend on the state of an object (actually steps don't have a state).
It would have been the state pattern if the whole survey had been modeled as an object with one method whose implementation depended on different states (in this case, the states would be the steps plus the action taken, i.e. surveyACompleted, surveyASkipped, surveyBCompleted, surveyBSkipped, etc, while the method would be something like nextStep()):
public class SurveyFlow {
private SurveyState state; // this represents the current step
public SurveyFlow(boolean skipFirst) {
this.state = skipFirst ? new SurveyASkipped() : new SurveyACompleted();
}
void setState(SurveyState state) {
this.state = state;
}
public void takeStep(boolean skipNext) { // takeStep operation delegated
// to the state (current step)
this.state.takeStep(skipNext, this); // "this" passed to the step so
// that it can switch to the
// next step if needed
}
}
The state would be polymorphically represented by each step of the SurveyFlow:
abstract class SurveyState {
protected abstract void takeStep(boolean skipNext, SurveyFlow survey);
}
Survey A states would be as follows:
class SurveyACompleted extends SurveyState {
protected void takeStep(boolean skipNext, SurveyFlow survey) {
// ...
survey.setState(skipNext ? new SurveyBSkipped() : new SurveyBCompleted());
}
}
class SurveyASkipped extends SurveyState {
protected void takeStep(boolean skipNext, SurveyFlow survey) {
// ...
survey.setState(skipNext ? new SurveyBSkipped() : new SurveyBCompleted());
}
}
Survey B states would be as follows:
class SurveyBCompleted extends SurveyState {
protected void takeStep(boolean skipNext, SurveyFlow survey) {
// ...
survey.setState(skipNext ? new SurveyCSkipped() : new SurveyCCompleted());
}
}
class SurveyBSkipped extends SurveyState {
protected void takeStep(boolean skipNext, SurveyFlow survey) {
// ...
survey.setState(skipNext ? new SurveyCSkipped() : new SurveyCCompleted());
}
}
For your example:
Complete Survey A
Skip Survey B
Complete Survey C
You could do:
SurveyFlow survey = new SurveyFlow(false); // will complete survey A
survey.takeStep(true); // completed survey A and will skip survey B
survey.takeStep(false); // skipped survey A and will complete survey C
survey.takeStep(true); // completed survey C
If survey C is the last step, then it can ignore the boolean argument and shouldn't set further steps.
This is in a way the State pattern, but does not completely adhere to the State pattern described by GoF, because you are not changing the state of a single object, but rather creating and returning a new object of different class which you use afterwards.
Actually, this resembles much more the Builder pattern, where the completeSurveyC() acts as a build or getResult method to build a Surway from multiple consisting pieces specified earlier.
I want to create an object of child class
more than 100 class extend MasterClass
MasterClass is
public class MasterClass{
int key;
String value;
String displayValue;
boolean status;
}
public class User extends MasterClass{
public User(){ }
}
public class Customer extends MasterClass{
String productName;
public Customer (){ }
}
etc...
i will get a MasterClass object from client, i wanted to type cast that object to respective one
if(masterClass instanceof User) {
User a_user = (User) a_ masterClass;
…
} else if(masterClass instanceof Customer) {
Customer a_customer = (Customer) a_ masterClass;
…
}
if i do this i will end up with 100s of else if.
Please let me know how i can achieve this without else if?
Thanks in advance.
Use polymorphism and generics, as Java intended.
Polymorphism lets you call a method on your object that behaves differently for every type. The easiest way to achieve this is to provide an abstract method in the base class MasterClass and then override it with different functionality in every extended class. You are probably looking for something like this:
class MasterClass {
int age;
// ...
public abstract void doWork();
public int getAge() { return age; }
// .. more methods
}
class User extends MasterClass {
// customize User here
#Override
public void doWork() { /* User does work in some way */ }
}
class Customer extends MasterClass {
// customize Customer here
#Override
public void doWork() { /* Customer does work in some other way */ }
}
// ...
If you are not too familiar with OOP, here is a good introductory tutorial.
If you are not allowed to alter your classes, you can populate a look-up table like HashMap<Class, MyFunctor> where you can assign a different functor for every type of person you have.
Also, you might want to use generics. Generics allow you to capture and restrict the type of objects passed to your methods.
Maybe you can use generics with the constraint T extends MasterClass?
Using basic concepts of Design Pattern you can create a constructor like this in the object where you try to initialize
MasterClass masterClass;
public MyCreatorOject(MasterClass masterClass)
{
this.masterClass = masterClass;
}
later when you create the object it can be
new MyCreatorObject(new User());
or
new MyCreatorObject(new Customer());