#java #simplify
Вопрос:
Я пытаюсь найти способ уменьшить длину и упростить следующие повторяющиеся методы :
boolean circleFlag, squareFlag, diamondFlag;
public void shapeButtonPressed(String shapeType) {
if (shapeType.equals("Circle")) {
circlePressed();
} else if (shapeType.equals("Square")) {
squarePressed();
} else if (shapeType.equals("Diamond")) {
diamondPressed();
}
}
public void circlePressed() {
if(!circleFlag){
//set only circleFlag true and the rest false.
circleFlag = true;
squareFlag = false;
diamondFlag = false;
//(... some code)
} else {
//set all flags false.
circleFlag = false;
diamondFlag = false
squareFlag = false;
//(... some different code)
}
}
public void squarePressed() {
if(!squareFlag){
//set only squareFlag true and the rest false.
squareFlag = true;
circleFlag = false;
diamondFlag = false;
//(... some code)
} else {
//set all flags false.
circleFlag = false;
diamondFlag = false
squareFlag = false;
//(... some different code)
}
}
public void diamondPressed() {
if(!diamondFlag){
//set only diamondFlag true and the rest false.
diamondFlag = true;
squareFlag = false;
circleFlag = false;
//(... some code)
} else {
//set all flags false.
circleFlag = false;
diamondFlag = false
squareFlag = false;
//(... some different code)
}
}
Вещи, которые я пробовал
Я попытался установить все свои значения в Boolean
тип, установить их в a ArrayList<Boolean>
и изменить shapePressed(String shapeType)
метод на
public void shapePressed(String shapeType) {
Boolean currFlag = false;
if (shapeType.equals("Circle")) {
currFlag = circleFlag;
} else if (shapeType.equals("Square")) {
currFlag = squareFlag;
} else if (shapeType.equals("Diamond")) {
currFlag = diamondFlag;
}
if (!currFlag){
for (Boolean flag : shapeFlag) flag = ( flag == currFlag ) ? true : false;
//(...)
} else {
for (Boolean flag : shapeFlag) flag = false;
//(...)
}
}
но строка ( flag == currFlag )
сравнивает логические значения как значения, а не как отдельные объекты. Так что мой currFlag
метод бессмыслен в этом вышеописанном методе.
Затем я подумал об использовании HashMap<String ,Boolean>
, но всякий раз, когда я сравниваю значения, заданные ключом (тип формы строки из параметра метода), я сталкиваюсь с той же проблемой, что и выше.
Как можно упростить этот код ?
Комментарии:
1. Вместо
if (circleFlag) { ...}
этого вы могли бы просто сделатьcircleFlag = !circleFlag;
, а затем установить другие флаги в значение false.2. Вероятно, существует множество способов сделать это, но я мог бы предложить использовать перечисление для представления ваших различных фигур и сохранить
currFlag
тип перечисления, который представляет текущую фигуру.
Ответ №1:
Когда заданная фигура активирована, вы просто переворачиваете этот флаг. Затем для других флагов устанавливается значение false.
Таким образом, тривиально, вы могли бы упростить свою circlePressed()
логику до:
public void circlePressed() {
circleFlag = !circleFlag;
squareFlag = false;
diamondFlag = false;
}
Конечно, все еще много повторений. Вы могли бы переработать это дальше в перечисление и отслеживать состояние там.
public enum Flag {
CIRCLE( false ),
SQUARE( false ),
DIAMOND( false ); // default state is false for all
private boolean state;
private Flag(boolean state) {
this.state = state;
}
public void flipState() {
this.state = !this.state;
}
public void setState(boolean state) {
this.state = state;
}
}
// notice this method takes the Flag not a string
public void shapeButtonPressed(Flag selected) {
// iterate through all the flags ...
for( Flag flag : Flag.values() ) {
if (flag == selected) {
// invert the "pressed" flag state
flag.flipState();
} else {
// ... and set the rest to false
flag.setState(false);
}
}
}
Встроенный values
метод перечислений возвращает список всех определенных перечислений, поэтому мы можем просто перебирать их.
Я признаю, что это немного хитроумно, так как на самом деле это не то, для чего предназначены перечисления, но это немного упрощает вашу логику.
Комментарии:
1. Я не совсем понимаю, зачем для начала отслеживать состояние по трем переменным, если только одна из них может быть истинной одновременно.
2.
activeState
Переменная может иметь смысл, но, к сожалению, мы мало знаем о вариантах использования, связанных с фрагментом кода.
Ответ №2:
Вы могли бы использовать перечисление.
public enum Shape {
CIRCLE, SQUARE, DIAMOND
}
Затем используйте это в своем коде следующим образом;
Shape shape;
public void shapeButtonPressed(Shape selectedShape) {
shape = selectedShape;
}
Если вы не можете изменить сигнатуру метода shapeButtonPressed
, и он должен принимать строку, вы все равно можете это сделать
Shape shape;
public void shapeButtonPressed(String shapeType) {
if (shapeType.equals("Circle")) {
shape = Shape.CIRCLE;
} else if (shapeType.equals("Square")) {
shape = Shape.SQUARE;
} else if (shapeType.equals("Diamond")) {
shape = Shape.DIAMOND;
}
}
Комментарии:
1. Можно написать более разумный выбор правильного перечисления вместо цепочки
if
. Вы можете выбрать, например, на основе его названия. Вы также можете ввести статическую функцию в класс перечисления, которая выполняет сопоставление за вас. Это всего лишь доказательство концепции, а не самый сложный способ ее решения.2. Если оператору необходимо иметь возможность «отменить выбор» фигуры при нажатии одной и той же кнопки фигуры, код также может быть тривиально изменен, чтобы установить
shape = null
, когдаshape == shapeType
не представлять выбор.3. @Йоханнес. Спасибо, я забыл о перечислениях. Но позже в моем коде, в других методах, у меня иногда бывает что-то вроде
if(circleFlag || squareFlag || diamondFlag) { //(...) }
. Означает ли это, что я не могу использовать предоставленный вами метод ?4. Вам просто нужно изменить код. Вы можете сделать либо
if (shape == Shape.SQUARE || shape == Shape.DIAMOND || shape == Shape.CIRCLE) {...}
то, либо другое, если этих трех фигур больше нет, просто используйтеif (shape != null) {...}
5. @JohannesH О да, это потрясающе ! Большое вам спасибо за вашу помощь :).
Ответ №3:
В качестве альтернативы моему подходу с перечислениями выше (который я настоятельно рекомендую по сравнению с этим), вы можете создать более «C-образное» решение, используя битовую маску вместо логических флагов.
Битовая маска-это, по сути, числовое (или двоичное, если на то пошло) значение, каждый бит которого представляет логическое значение.
int shapeFlags;
public void shapeButtonPressed(String shapeType) {
if (shapeType.equals("Circle")) {
shapeFlags = 1;
} else if (shapeType.equals("Square")) {
shapeFlags = 2;
} else if (shapeType.equals("Diamond")) {
shapeFlags = 4;
}
}
Это по-прежнему оставляет вам возможность установить более одной фигуры true
, при этом вы можете переопределить все флаги за одну операцию.
Сопоставления числовых значений с фигурами будут выглядеть следующим образом:
0 : no shape
1 : circle
2 : square
3 : circle amp; square
4 : diamond
5 : diamond amp; circle
6 : diamond amp; square
7 : all three