Может быть, когда-то ты слышал, есть такая штука как "программирование на интерфейсах". Пора познакомиться с этим поближе. Тут будет мало текста и много кода (без логики).
Я не смог найти, когда появились первые интерфейсы. Наверно это было очень давно, и интернет об этом забыл. Ну да ладно. Идея интерфейса простая: описать, что мы будем делать без подробностей. Т.е. неважно, как вы это сделаете, важно, что вы сделаете.
Зато после того, как я написал эту статью, я нашел хорошую, на похожую тему, тут в группах. Жмакай по ссылке и читай, чем больше, тем лучше!
Содержимое:
Зачем это нужно?
Когда код состоит из одного класса, это нафиг не нужно. Но когда классы должны взаимодействовать между собой, а их количество — переваливать за несколько десятков, тут впору задуматься о проектировании. Сначала продумать всю структуру проекта сверху вниз (от максимальной абстракции к реализации). Если над проектом работает несколько человек, то очень удобно договориться, описать интерфейсы взаимодействия классов, потом разобрать эти интерфейсы и начать реализовывать. Получается хорошая параллельность задач, их легко делить, т.к. все обо всем договорились, а подробности никого не волнуют.Что это дает разработчику?
Разработчику не нужна реализация класса. Это значит, что после того как все договорились, он берет нужные ему интерфейсы и пользуется ими. Реализация будет подставлена, когда будет готова. Давай я покажу свой пример, и потом поговорим дальше. Я решил написать небольшой проект кассы. Она будет помогать выбирать билеты, продавать их, сдавать деньги в банк и брать из банка, менять деньги для понаехавших. Итак, мой архитектурный выдох: P.S. не надо копировать и создавать структуру, для лиги лени я приложил архивчик с кодом в конце статьи ;) Структура:Куча моделек:
package cashbox.model;
public enum Currency {
USD,
EUR,
RUR
}
package cashbox.model;
public interface Direction {
/**
* @return город как цель направления, куда едем/летим/двигаемся
*/
String getCity();
}
package cashbox.model;
/**
* модель денег
*/
public interface Money {
/**
* @return тип валюты
*/
Currency getCurrency();
/**
* @return сумма денег
*/
long getAmount();
}
package cashbox.model;
public interface Ticket {
/**
* @return направление куда двигаемся
*/
Direction getDirection();
/**
* @return цена билета
*/
Money getPrice();
/**
* @return транспорт на котором передвигаемся
*/
Transport getTransport();
}
package cashbox.model;
public interface Transport {
}
Пара exception:
package cashbox.exception;
public class NoSoMuchMoneyException extends RuntimeException {
}
package cashbox.exception;
import cashbox.model.Money;
public class NoSuchCurrencyException extends RuntimeException {
private Money money;
public NoSuchCurrencyException(Money money) {
this.money = money;
}
public NoSuchCurrencyException(String message, Money money) {
super(message);
this.money = money;
}
public Money getMoney() {
return money;
}
}
Касса — самая важная часть:
package cashbox;
import cashbox.exception.NoSoMuchMoneyException;
import cashbox.exception.NoSuchCurrencyException;
import cashbox.model.*;
import javafx.util.Pair;
import java.util.List;
import java.util.Map;
public interface CashBox {
/**
* @param direction направление билета
* @return Стоимость проезда по видам транспорта
*/
Map<Transport, Money> getPrice(Direction direction);
/**
* Продать билет
* @param money деньги за билет
* @return пару из билета и сдачи
*/
Pair<Ticket, Money> sellTicket(Money money);
/**
* обмен валюты
* @param moneyFrom валюта, которую передает клиент
* @param currency валюта, которую клиент хочет получить, тут будет учитываться только тип валюты,
* количество будет проигнорировано
* @return Требуемая валюта
* @throws NoSoMuchMoneyException если недостаточно денег в кассе для обмена
* @throws NoSuchCurrencyException если нет такой валюты, отсутствующая валюта передается как атрибут
*/
Money change(Money moneyFrom, Currency currency) throws NoSoMuchMoneyException, NoSuchCurrencyException;
/**
* Инкасация - отправить деньги в банк
* @param money - сумма и валюта, можно передать несколько
*/
void sendToBank(Money... money);
/**
* Запрос денег из банка
* @param money - сумма и валюта необходимая кассе
*/
void requestFromBank(Money... money);
/**
* Подбор билета.
* В метод передается либо одно, либо другое, либо вместе.
* Если оба атрибута null значит вызов некорректный
* @param transport - желаемый транспорт
* @param direction - желаемое направление
* @return список подходящих билетов
*/
List<Ticket> chooseBy(Transport transport, Direction direction);
}
Первое, что бросается в глаза не подготовленному разработчику, это javadoc
. Хотя, наверно, неподготовленному разработчику как раз они привычны. Это некоторые иногда лентяйничают, мой же код и так хорош, без доки ;) Мне даже сейчас на некоторые вещи не хочется писать доку. Ну зачем писать транспорту, что это транспорт? Оставим это на потом!
Я постарался доками описать все, что надо. Теперь объясню, почему так писать код удобнее.
Смотри, я сейчас могу дать тебе интерфейс CashBox
и попросить его реализовать. Он же не трудный? Плюс требуемое поведение описано в документации. Тебе не надо будет ждать, пока кто-то напишет модели или ещё что-то. Ты берешь модели интерфейсов и начинаешь работать на их основе. Теперь ты программируешь на интерфейсах, поздравляю. А теперь главное. Я могу дать тебе задачу реализовать CashBox
, а так же ещё кому-то, чтобы у нас было 2 реализации. Например, пригородная и международная касса. Вы сможете писать код параллельно и любой член команды, который будет писать код на основе CashBox
, может уже начинать и опираться на интерфейс. Это очень удобно. Многозадачность, чтоб её.
Ссылка на код на гугл диске -> тут
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ