Amazon Interview Question for SDE-2s


Country: India
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
0
of 2 vote

The main idea is to implement the Observable architecture.
We need to create OrderManager Class that observe Order Class for status changes.

package com.cracking.amazon;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

public class AmazonOrders {
	
	
	public static interface Observer<T> {
		public void onChange(T subject);
	}
	
	public static interface Subject<T>{
		public boolean registerObserver(Observer<T> observer);
		public void notifyAllObservers();
		public boolean deleteObserver(Observer<T> observer);
	}
	
	public static enum OrderStatus {
		Received("Received"),
		Assigned("Assigned"),
		Delivered("Delivered"),
		PickedUp("PickedUp");
		
		public String description;
		
		OrderStatus(String description) {
			this.description = description;
		}
	}
	
	public static class DeliveryBoy {
		private int id;
		private String name;
		
		public DeliveryBoy(int id, String name){
			this.id = id;
			this.name = name;
		}
	}
	
	public static class Order implements Subject<Order> {
		
		private ArrayList<Observer<Order>> observers;
		private int id;
		private Date expectedTime;
		private OrderStatus status;
		private DeliveryBoy deliveryBoy;
		
		public Order(int id, Date expectedTime){
			this.observers = new ArrayList<Observer<Order>>();
			this.id = id;
			this.expectedTime = expectedTime;
		}
		
		public int getId(){
			return this.id;
		}
		
		public void assignDeliveryBoy(DeliveryBoy deliveryBoy) {
			this.deliveryBoy = deliveryBoy;
			this.setStatus(OrderStatus.Assigned);
		}
		
		public void setStatus(OrderStatus status) {
			this.status = status;
			this.notifyAllObservers();
		}

		@Override
		public boolean registerObserver(Observer<Order> observer) {
			if(!this.observers.contains(observer)) {
				this.observers.add(observer);
				return true;
			}
			return false;
		}

		@Override
		public boolean deleteObserver(Observer<Order> observer) {
			return this.observers.remove(observer);
		}

		@Override
		public void notifyAllObservers() {
			for(Observer<Order> observer:this.observers) {
				observer.onChange(this);
			}
		}
	}
	
	public static class OrderManager implements Observer<Order> {
		
		private ArrayList<Order> orders;
		
		public OrderManager() {
			this.orders = new ArrayList<Order>();
		}
		
		public boolean addOrder(Order order) {
			if(!this.orders.contains(order)){
				this.orders.add(order);
				order.registerObserver(this);
				order.setStatus(OrderStatus.Received);
				return true;
			}
			
			return false;
		}

		@Override
		public void onChange(Order subject) {
			// TODO Auto-generated method stub
			String msg = String.format("Order #%d status changed - %s", 
					subject.getId(),
					subject.status.description);
			System.out.println(msg);
		}
		
	}
	
	public static void main(String[] args) {
		OrderManager orderManager = new OrderManager();
		DeliveryBoy mainDeliveryBoy = new DeliveryBoy(100, "Main Delivery Boy");
		
		Calendar cal = Calendar.getInstance(); 
		cal.setTime(new Date());
		cal.add(Calendar.DATE, 2);
		Date date1 = cal.getTime();

		Order order1 = new Order(1, date1);
		
		//Order Received
		orderManager.addOrder(order1);
		
		//Order Assigned
		order1.assignDeliveryBoy(mainDeliveryBoy);
		
		//Order Delivered
		order1.setStatus(OrderStatus.Delivered);
		
		//Picked Up
		order1.setStatus(OrderStatus.PickedUp);
		
	}

}

***In the onChange method of the OrderManager you can switch between status cases and print custom messages for each case.

Output:

Order #1 status changed - Received
Order #1 status changed - Assigned
Order #1 status changed - Delivered
Order #1 status changed - PickedUp

- ProTechMulti September 10, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Another to design this using an Event driven architecture. The difference from the Observer pattern is that EDA asynchronously delivers message/event to the Subscriber.

import java.util.Date;

public class Order {
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getDate() {
        return new Date();
    }

    public Order (int id) {
        this.id = id;
    }
}

- BigPug January 29, 2018 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Sorry I hit the Submit button too soon. Here is the complete answer.

Another way to design this using an Event Driven Architecture. The difference from the Observer pattern is that EDA asynchronously delivers message/event to the Subscriber. As a subscriber you subscribe to a central Event Keeper - EventDispatcher - in this case; and maybe go ahead and do other tasks. When the dispatch is done, the Event will be sent to you later.

import java.util.Date;

public class Order {
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getDate() {
        return new Date();
    }

    public Order (int id) {
        this.id = id;
    }
}

public interface Event {
    Class<? extends Event> getType();
}

public interface Handler<E extends Event> {
    public void onEvent(E event);
}

public class DeliveryBoy {
    private String name;

    public DeliveryBoy(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

public abstract class AbstractEvent implements Event {
    public Class<? extends Event> getType() {
        return getClass();
    }
}

import java.util.HashMap;
import java.util.Map;

public class EventDispatcher {
    private Map<Class<? extends Event>, Handler<? extends Event>> handlers;

    public EventDispatcher() {
        handlers = new HashMap<>();
    }

    public <E extends Event> void registerHandler(Class<E> eventType, Handler<E> handler) {
        handlers.put(eventType, handler);
    }

    public <E extends Event> void dispatch(E event) {
        Handler<E> handler = (Handler<E>) handlers.get(event.getClass());

        if (handler != null) {
            handler.onEvent(event);
        }
    }
}

public class OrderReceivedEvent extends AbstractEvent {
    private Order order;

    public OrderReceivedEvent(Order order) {
        this.order = order;
    }

    public Order getOrder() {
        return this.order;
    }
}

public class UserAssignedEvent extends AbstractEvent {
    private DeliveryBoy boy;
    private Order order;

    public UserAssignedEvent(DeliveryBoy boy, Order order) {
        this.boy = boy;
        this.order = order;
    }

    public DeliveryBoy getDeliveryBoy() {
        return this.boy;
    }
    public Order getOrder() { return this.order; }
}

public class OrderPickedUpEvent extends AbstractEvent {
    private Order order;

    public OrderPickedUpEvent(Order order) {
        this.order = order;
    }

    public Order getOrder() {
        return this.order;
    }
}

public class OrderDeliveredEvent extends AbstractEvent {
    private Order order;
    private DeliveryBoy boy;

    public OrderDeliveredEvent(DeliveryBoy boy, Order order) {
        this.order = order;
        this.boy = boy;
    }

    public Order getOrder() {
        return this.order;
    }

    public DeliveryBoy getDeliveryBoy() {
        return this.boy;
    }
}

public class OrderReceivedEventHandler implements Handler<OrderReceivedEvent> {
    @Override
    public void onEvent(OrderReceivedEvent event) {
        System.out.println("Order ID - " + event.getOrder().getId() + " - Received on Date - " + event.getOrder().getDate());
    }
}

public class UserAssignedEventHandler implements Handler<UserAssignedEvent> {
    @Override
    public void onEvent(UserAssignedEvent event) {
        System.out.println("Delivery boy - " + event.getDeliveryBoy().getName() + " - is assigned to the Order ID - " + event.getOrder().getId());
    }
}

public class OrderPickedUpEventHandler implements Handler<OrderPickedUpEvent> {
    @Override
    public void onEvent(OrderPickedUpEvent event) {
        System.out.println("Order ID - " + event.getOrder().getId() + " - picked up on Date - " + event.getOrder().getDate());
    }
}

public class OrderDeliveredEventHandler implements Handler<OrderDeliveredEvent> {
    @Override
    public void onEvent(OrderDeliveredEvent event) {
        System.out.println("Order ID - " + event.getOrder().getId() + " - delivered on Date - " + event.getOrder().getDate() + " - by Delivery Boy - " + event.getDeliveryBoy().getName());
        System.out.println();
    }
}

public class TestEvent {
    public static void main(String[] args) {
        Queue<String> deliveryBoys = new LinkedList<>();
        String[] nameOfDeliveryBoys = {"Tom", "Dick", "Harry", "Gordon", "Leon", "Michael"};

        for (int i = 0; i < 10; i ++) {
            deliveryBoys.add(nameOfDeliveryBoys[(int)(Math.random() * nameOfDeliveryBoys.length)]);
        }

        Queue<Order> orders = new LinkedList<>();

        for (int j = 1; j <= 10; j++) {
            orders.add(new Order(j));
        }

        EventDispatcher dispatcher = new EventDispatcher();

        dispatcher.registerHandler(OrderReceivedEvent.class, new OrderReceivedEventHandler());
        dispatcher.registerHandler(UserAssignedEvent.class, new UserAssignedEventHandler());
        dispatcher.registerHandler(OrderPickedUpEvent.class, new OrderPickedUpEventHandler());
        dispatcher.registerHandler(OrderDeliveredEvent.class, new OrderDeliveredEventHandler());

        while(!orders.isEmpty()) {
            DeliveryBoy deliveryBoy = new DeliveryBoy(deliveryBoys.poll());
            Order currentOrder = orders.poll();

            dispatcher.dispatch(new OrderReceivedEvent(currentOrder));
            dispatcher.dispatch(new UserAssignedEvent(deliveryBoy, currentOrder));
            dispatcher.dispatch(new OrderPickedUpEvent(currentOrder));
            dispatcher.dispatch(new OrderDeliveredEvent(deliveryBoy, currentOrder));
        }
    }
}

- BigPug January 29, 2018 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More