2014-11-28 1 views
5

Предположим, что у меня есть n boolean values, где n - относительно небольшое число (3-5 или около того). Предположим, что значения - это свойства класса, каждый из которых может быть установлен или отключен независимо. Итак, есть 2 n возможные комбинации. Теперь я хочу различать эти комбинации переключающим образом. В настоящее время я обычно делаю что-то вроде этого:Конструкция переключателя для комбинаций булевых координат

int mask = (bool1 ? 1 : 0) + 
      (bool2 ? 2 : 0) + 
      (bool3 ? 4 : 0) + 
      ... ; 
switch (mask) { 
    case 0b000: 
     // all variables false 
    case 0b001: 
     // only bool1 true 
    case 0b011: 
     // only bool1 and bool2 true 
    ... 
} 

Это работает хорошо, но я не считаю его очень изящным. Есть ли какая-то передовая практика (на Java) или идиома Java для таких случаев?

+0

Почему вы не используете инструкцию if? Это будет гораздо более читаемым, чем этот переключатель. – DontRelaX

+0

Этот ** может быть более подходит для [обзора кода] (http://codereview.stackexchange.com/), хотя и не голосовал, чтобы закрыть сомнения. – Mena

+0

@ DontRelaX Theres несколько способов сделать ifs, почему бы вам не поместить ваше предпочтение в качестве ответа. И подумайте, как это будет выглядеть, если у вас 5 балов. – weston

ответ

0

Эта проблема является причиной того, что они изобрели Decorator Design Pattern. Шаблон позволяет добавлять «черты» в ваш класс. Например, скажем, у вас есть класс Coffee. Каждый экземпляр кофе может быть с сахаром, молоком, сливками, подсластителем или взбитыми сливками (скажем, ни один из них не является взаимоисключающим). Поэтому вместо пяти логических параметров (по одному для каждой характеристики кофе). Вы будете иметь следующую иерархию:

public interface Coffee { 
    public void drink(); 
} 

public class CupOfCofee implements Coffee { 
    public void drink() { 
    print("Yumm coffee"); 
    } 
} 

abstract class CoffeeDecorator implements Coffee { 
    protected Coffee decoratedCoffee; 

    public CoffeeDecorator(Coffee decoratedCoffee) { 
    this.decoratedCoffee = decoratedCoffee; 
    } 

    public void drink() { 
    decoratedCoffee.drink(); 
    } 
} 

// We will provide coffee with sugar as an example. 
public class CoffeeWithSugarDecorator extends CoffeeDecorator { 
    public CoffeeWithSugarDecorator(Coffee decoratedCoffee) { 
    super(decoratedCoffee); 
    } 

    @Override 
    public void drink() { 
    print("Yumm sugar"); 
    super.drink(); 
    } 
} 

// Here is how you will initialize a coffee instance with sugar and milk. 
Coffee coffee = new CoffeeWithMilk(new CoffeeWithSugar(new CupOfCoffee())); 

Такая конструкция делает ваш код более читаемым и расширяемый путем разделения поведения каждого логического параметра в отдельный класс. Вызывающий напиток будет печатать: «Yumm milk Yumm sugar Yumm coffee»

+0

Спасибо за ответ. Это интересный шаблон дизайна, но я не думаю, что он полностью решает проблему. Во-первых, невозможно указать, что некоторый код должен быть запущен, если украшение * не * присутствует. Во-вторых, если 'Coffee' украшен' CoffeeWithMilk' и 'CoffeeWithSugar', выполняется метод' drink() 'обоих украшений. Тем не менее, я могу захотеть запустить блок кода A, если молоко истинно, блок кода B, если сахар является истинным, и полностью не связанный блок C, если оба сахара и молока являются истинными. Может быть, если шаблон декоратора может быть адаптирован для поддержки этого? – Hoopje

+0

Что касается кода для небывалого украшения, вы можете написать класс CoffeeWithoutMilk. Затем вы можете написать что-то вроде нового CoffeeWithoutMilk (новый CoffeeWithSugar (новый CupOfCoffee())); Вы можете написать еще один класс под названием CoffeeWithSugarAndMilk, который сделает что-то совершенно иное, чем CoffeeWithSugar и CoffeeWithMilk. Единственная проблема заключается в том, что пользователи должны знать, использовать этот класс, а не создавать новый CoffeeWithMilk (новый CoffeeWithSugar (новый CupOfCoffee())); –

Смежные вопросы