直和型(列挙型にフィールドを付加したもの)を利用することで、複数の直積型を定義する。
type button = Bar | Line | Scatter
type state =
OverWrite of button list
| Normal of button
let on_button_click b = function
| OverWrite bs when List.exists((=) b) bs -> OverWrite (List.filter((<>) b) bs)
| OverWrite bs -> OverWrite (b::bs)
| Normal _ -> Normal b
- Java には列挙型(Enum)があるが、直和型はないため、
- Enum とフィールドを合わせ持つ ValueObject Group 的なクラス ButtonsState で表現する
//ボタン状態を管理するVOGroup
public static class ButtonsState {
public final State state;
public final Selected selected;
//ファクトリ
public ButtonsState newState(final Button button) {
if (state.equals(State.OverWirte)) {
if (selected.contains(button)) {
return new ButtonsState(this.state, this.selected.remove(button));
}
else {
return new ButtonsState(this.state, this.selected.add(button));
}
}
return new ButtonsState(this.state, new Selected(button));
}
//ファクトリ
public ButtonsState newState(final State state) {
return new ButtonsState(state, this.selected);
}
//コンストラクタ
ButtonsState(final State state, final Selected selected) {
this.state = state;
this.selected = selected;
}
//重ね描画種別
public static enum State { OverWirte, Normarl; }
//ボタン種別
public static enum Button { Bar, Line, Scatter; }
//選択されているボタン群を表現するVO
public static class Selected {
public final List<Button> buttons;
//コンストラクタ
public Selected(final Button button) {
this(Arrays.asList(button));
}
//コンストラクタ
public Selected(final List<Button> buttons) {
this.buttons = Collections.unmodifiableList(buttons);
}
public boolean contains(final Button button) {
return buttons.contains(button);
}
public Selected remove(final Button button) {
final List<Button> newList = new ArrayList<>(buttons);
newList.remove(button);
return new Selected(buttons);
}
public Selected add(final Button button) {
final List<Button> newList = new ArrayList<>(buttons);
newList.add(button);
return new Selected(buttons);
}
}
}
うーん、さすがJava。コードが長い。。