Оператор (+) указывает внешнее соединение. Это означает, что Oracle по-прежнему будет возвращать записи с другой стороны соединения, даже если нет совпадения. Например, если a и b являются emp и dept, и у вас могут быть сотрудники, не назначенные для отдела, тогда следующий оператор будет возвращать сведения о всех сотрудниках независимо от того, назначен ли они отделу.
select * from emp, dept where emp.dept_id=dept.dept_id(+)
Короче говоря, удаление (+) может иметь разницу в значении, но вы можете не заметить какое-то время в зависимости от ваших данных!
BillBundle
в качестве объекта параметра представляет собой масштабируемый подход для сокращения списка параметров методов. Как и любая реализация шаблона проектирования объекта параметра , подразумевает также перемещение по коду, обрабатывающему параметры. Опция, позволяющая избежать дублирования кода при получении счетов и передачи их таким методам, как depositCash
, может быть совмещена между шаблоном дизайна посетителя для получения счетов и шаблоном разработки метода шаблона обрабатывать их
Предполагая, что информация, используемая для расчета счетов, поступает из банкомата, эмитент счета может вычислить счета и принять в качестве посетителя обработчик счета, который получает счета и обрабатывает их
interface BillEmitter {
int getFives();
int getTens();
int getTwenties();
int getFifties();
default void accept(Visitor v) {
v.visit(this);
}
}
// add BillEmitter implementations as needed
public class SomeBillEmitter implements BillEmitter {
private Atm atm;
public SomeBillEmitter(Atm atm) {
this.atm = atm;
}
public int getFives() {
int theFivesBill = 0;
// compute the fives bill with the information from ATM
return theFivesBill;
}
public int getTens() {
int theTensBill = 0;
// compute the tens bill with the information from ATM
return theTensBill;
}
public int getTwenties() {
int theTwentiesBill = 0;
// compute the twenties bill with the information from ATM
return theTwentiesBill;
}
public int getFifties() {
int theFiftiesBill = 0;
// compute the fifties bill with the information from ATM
return theFiftiesBill;
}
}
Посетители
interface Visitor {
default void visit(BillEmitter billEmitter) {
// template method which gets the bills from the billEmitter
// and pass them to the bill processor
Billbundle billBundle = new BillBundle();
billBundle.setFives(billEmitter.getFives());
billBundle.setTens(billEmitter.getTens());
billBundle.setTwenties(billEmitter.getTwenties());
billBundle.setFifties(billEmitter.getFifties());
processBills(billBundle);
}
void processBills(BillBundle billBundle);
}
// add Visitor implementations as needed
public class DepositCashVisitor implements Visitor {
public void processBills(BillBundle billBundle) {
// deposit the cash
...
}
}
Использование
public class Atm {
// add methods which returns information used to emit bills
}
public class Test {
public static void main(String[] args) {
Visitor depositCashVisitor = new DepositCashVisitor();
Atm atm = new Atm();
BillEmitter billEmitter = new SomeBillEmitter(atm);
billEmitter.accept(depositCashVisitor);
// add more bill emitters and visit them with depositCashVisitor
// or add more visitors and visit billEmitter with them
}
}
Ваша BillBundle
идея выглядит хорошо для меня. Вы говорите, что вам приходилось многократно писать код:
Billbundle billBundle = new BillBundle();
billBundle.setFives(fives);
billBundle.setTens(tens);
billBundle.setTwenties(twenties);
billBundle.setFifties(fifties);
depositCash(billBundle);
Но действительно ли вы действительно или просто думаете, что можете?
Подобное BillBundle
должно действительно быть сделано только тогда, когда счета подсчитаны , и я был бы удивлен, если бы это произошло более чем в нескольких местах.
Код, который на самом деле не изменяется и не определяет номер каждого счета, должен просто распространяться по пакету счетов. Метод, который регистрирует, сколько счетов каждого вида было внесено? Передайте BillBundle
, что вы получили от подсчета. Метод, который складывает общую сумму денег? Передайте BillBundle
, что вы получили от подсчета. и т. д. и т. д.
Это гораздо лучше, чем обойти 4 параметра повсеместно по двум причинам:
Гораздо меньше возможностей все испортить - каждая функция, которая принимает 4 параметра счета и передает у них в другом месте есть шанс передать их в неправильном порядке или в неправильных положениях параметров. Это особенно проблематично, поскольку фактические значения имеют один и тот же тип (т.е. int
), и многие аргументы используют этот тип для совершенно разных вещей.
Гораздо меньше кода на самом деле зависит от типов счетов, которые вы поддерживаете. Допустим, ваша страна переключается на монету в 5 долларов, или вы просто не хотите, чтобы они были в машинах больше ... сколько кода нужно изменить, чтобы избавиться от пятерок? Вам нужно будет изменить код, который подсчитывает счета, и все остальные вещи, которые на самом деле заботятся о суммах каждого счета, но вам не нужно менять код, который просто пропускает эти счета. Они могут просто обойти оригинал BillBundle
и не беспокоиться об этом.
Одно изменение, которое я бы предложил, - сделать ваш BillBundle неизменным. Тогда вам не нужно беспокоиться о том, чтобы кто-нибудь изменил его, когда вы передаете его.
Что-то вроде:
class BillBundle
{
public final int fives;
public final int tens;
public final int twenties;
public final int fifties;
public BillBundle(int fives, int tens, int twenties, int fifties)
{
this.fives = fives;
this.tens = tens;
this.twenties = twenties;
this.fifties = fifties;
}
}
Я предупрежу вас, что большинство Java-программистов предпочитают методы getter вместо открытых полей final, но для этого нет веских причин.