I need some help in working Video Rental Store application design optimization.  The application describes the following tasks:Inventory stores videos. Inventory can add/delete/change and receive all videos. Inventory has 3 types of films: Old, New, Regular.Videos have a title, type (described above) and availability which will be changed to 'not available'/'available' if this video is rented by someone.Customer can rent only available videos(not rented by someone) with additional option to rent film for bonus points which gathers every time when a customer rents a video (1 point for rent)Before the customer rents a video he/she set renting days. The price for rent calculated automatically based on rent days, video type. After the price is calculated for this rent transaction than customer is presented terms where he/she has a choice to accept or reject them. If a customer accepts terms than rent transaction is executed successfully.Data is not persisted anywhere, data exists in runtime. Inventory and RentalStore class generates some fake records for presentation.Could you please review my app and offer some tips or optimization tricks?In general, I'm not sure in RentalStore class which implements connections to the Inventory and RentalTransactions classes. I don't know how to implement elegant class which will work with rental transactions and will know what items have inventory. I read some principles of design patterns how to organize application that it will be flexible as much as possible but it seems I need more experience in design area. That is why I contact with you. Someone suggested me that it is possible to do it better than my way.RentalStore class:public interface RentalDAO {void rentItem(Person person, Item item, int days, Boolean temsAcceptance);List<RentalTransaction> getAllRentals();List<RentalTransaction> getAllRentalsForCustomer(Person person);}public class RentalStore implements RentalDAO {    private Inventory inventory;    private List<RentalTransaction> rentalTransactions;    public RentalStore() {        this.inventory = new Inventory();        this.rentalTransactions = new LinkedList<RentalTransaction>();        generateFakeRentalTransactions();    }    public Inventory getInventory() {        return inventory;    }    private void generateFakeRentalTransactions() {        rentItem(new Customer(Kauri), inventory.getAllAvailableItems().get(new Random().nextInt(inventory.getAllAvailableItems().size() - 1) + 1), new Random().nextInt(30) + 1, true);        rentItem(new Customer(Lauri), inventory.getAllAvailableItems().get(new Random().nextInt(inventory.getAllAvailableItems().size() - 1) + 1), new Random().nextInt(30) + 1, true);    }    @Override    public void rentItem(Person person, Item item, int days, Boolean temsAcceptance) {        if (item.isAvailable()) {            RentalTransaction newRentalTransaction = new RentalTransaction(person, item, days, temsAcceptance);            if (!rentalTransactions.contains(newRentalTransaction)) {                rentalTransactions.add(newRentalTransaction);            }        }    }    @Override    public List<RentalTransaction> getAllRentals() {        return rentalTransactions;    }    @Override    public List<RentalTransaction> getAllRentalsForCustomer(Person person) {        List<RentalTransaction> rentalTransactionsForCustomer = new LinkedList<RentalTransaction>();        for (RentalTransaction rentalTransaction : rentalTransactions) {            if (rentalTransaction.getPerson().equals(person)) {                rentalTransactionsForCustomer.add(rentalTransaction);            }        }        return rentalTransactionsForCustomer;    }}In RentalStore class I don't like also that rentItem() method has hardcoded Person argument. It doesn't take me, for instance, define this object is really Customer or, may be, employee. Also it doesn't take me to invoke person.chargeBonus() due to it concern only to Customer objects. I can do so (CUstomer) person.chargeBonus() but it can cause Exception in some cases and looks somehow bad, how to optimize it too?RentalTransaction class:public class RentalTransaction {private static final double PREMIUM_FEE = 40;private static final double REGULAR_FEE = 30;private Person person;private Item item;private int days;private double price;private boolean termsAcceptance;public RentalTransaction(Person person, Item item, int days, boolean termsAcceptance) {    this.person = person;    this.item = item;    this.days = days;    this.price = calculate();    this.termsAcceptance = termsAcceptance;}public Person getPerson() {    return person;}public Item getItem() {    return item;}public int getDays() {    return days;}public void setDays(int days) {    this.days = days;    this.price = calculate();}public double getPrice() {    return price;}private double calculate() {    switch (item.getType()) {        case NEW_RELEASES:            this.price = PREMIUM_FEE * days;            break;        case REGULAR:            if (days > 3) {                this.price = REGULAR_FEE + REGULAR_FEE * (days - 3);            } else {                this.price = REGULAR_FEE * days;            }            break;        case OLD:            if (days > 5) {                this.price = REGULAR_FEE + REGULAR_FEE * (days - 5);            } else {                this.price = REGULAR_FEE * days;            }            break;    }    return this.price;}public boolean isTermsAccepted() {    return termsAcceptance;}public void setTermsAcceptance(boolean termsAcceptance) {    this.termsAcceptance = termsAcceptance;}}Inventory class:public class Inventory implements InventoryDAO {private static String[] itemNames = {Shrek, Spider Man III, Game of Thrones, Mortal Combat};private List<Item> items;public Inventory() {    items = new LinkedList<Item>();    for (String itemName : itemNames) {        items.add(new Item(itemName, true, Type.getRandom()));    }}@Overridepublic void addItem(Item item) {    if (!items.contains(item))        items.add(item);}@Overridepublic void removeItem(Item item) {    if (items.contains(item))        items.remove(item);}@Overridepublic void changeItemType(String title, Type type) {    for (Item item : items) {        if (item.getTitle().equals(title) && !item.getType().equals(type)) {            item.setType(type);        }    }}@Overridepublic List<Item> getAllItems() {    return items;}@Overridepublic List<Item> getAllAvailableItems() {    List<Item> availableItems = new LinkedList<Item>();    for (Item item : items) {        if (item.isAvailable())            availableItems.add(item);    }    return availableItems;}}public interface InventoryDAO {void addItem(Item item);void removeItem(Item item);void changeItemType(String title, Type type);List<Item> getAllItems();List<Item> getAllAvailableItems();}Another thing is Type class.  Is it possible to do base enum Type class for Item and redefine it to concrete enum type in Video class, as example?Type class:public enum Type {    NEW_RELEASES(New Releases),    REGULAR(Regular),    OLD(Old);    private final String type;    private Type(String type) {        this.type = type;    }    public static Type getRandom() {        return values()[(int) (Math.random() * values().length)];    }    @Override    public String toString() {        return type;    }}Where I use type(is it possible to make base enum Type class for redefining in Video class?):public class Item {    private String title;    private boolean avability;    private Type type;    public Item(String title, Boolean avability, Type type) {        this.title = title;        this.avability = avability;        this.type = type;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public Boolean isAvailable() {        return avability;    }    public void setAvability(boolean avability) {        this.avability = avability;    }    public Type getType() {        return type;    }    public void setType(Type type) {        this.type = type;    }}Any suggestions?
Video rental store application design
java