【问题标题】:Decorator Pattern Piano Application装饰图案钢琴应用
【发布时间】:2016-05-08 13:29:27
【问题描述】:

我正在尝试应用装饰器模式,但到目前为止,我无法让它按照我想要的方式工作。

基本上,我正在尝试创建一个钢琴应用程序,它有一个扩展 JavaFX 矩形的钢琴键超类和两个子类白键和黑键,当您将鼠标悬停在它们上面时,它们都有方法的实现。

它们工作正常,但我现在正在尝试创建装饰器类,这些装饰器类将通过提供自己的播放方法并为该装饰器的音频文件附加相关字​​符串来覆盖超类的播放方法。 例如PianoKeyViolinDecorator 会在播放之前将“violin”附加到音频文件名的末尾。

播放方法有效,但将鼠标悬停在矩形上的方法无效。除非我在装饰器中设置高度和宽度,否则矩形不会显示在我的 GUI 中。有什么方法可以让钢琴键的矩形显示出来,而不必在 Decorator 类中重新创建一个新的矩形?

这是我的装饰器类:

public class PianoKeyDecorator extends KeyView {

private KeyView keyView;

public PianoKeyDecorator(KeyView keyView) {
    this.keyView = keyView;
}

public void lightOn() {
    keyView.lightOn();
}

public void lightOff() {
    keyView.lightOff();
}

@Override
public void play() {
    AudioClip audioFile = new AudioClip(AssignmentTemplate.class.getResource(keyView.keyAudioSource() + "_violin.wav").toExternalForm());
    audioFile.play();
}

还有我的超类

public abstract class KeyView extends Rectangle {

private AudioClip keyAudio;
private String keyAudioSource;
private String keyId;
private String background;
private String backgroundHover;

public KeyView(double width, double height, String keyAudioSource, String keyText, String background, String backgroundHover) {
    this.keyAudioSource = keyAudioSource;
    keyAudio = new AudioClip(AssignmentTemplate.class.getResource(keyAudioSource + ".wav").toExternalForm());
    this.background = AssignmentTemplate.class.getResource("resources/"+ background).toExternalForm();
    this.backgroundHover = AssignmentTemplate.class.getResource("resources/"+ backgroundHover).toExternalForm();
    this.getStyleClass().add("key");
    setWidth(width);
    setHeight(height);
}

public KeyView(){}

public void play() {
    keyAudio.play();
}

public void setAudioClip(AudioClip keyAudio) {
    this.keyAudio = keyAudio; 
}

public abstract void lightOn();
public abstract void lightOff();    

public void setKeyId(String keyId) {
    this.keyId = keyId;
}

public String getKeyId() {
    return keyId;
}

public String getBackground() {
    return background;
}

public String getBackgroundHover() {
    return backgroundHover;
}

public String keyAudioSource() {
    return keyAudioSource;
}

这是我的一个子类

公共类 BlackKeyView 扩展 KeyView {

public SharpKeyView(String keyAudioFile, String keyText, String background, String backgroundHover) {
        super(64, 170, keyAudioFile, keyText, background, backgroundHover);
        setKeyId("sharp" + keyText);
}

public void lightOn() {
    super.setFill(Color.BLUE);
}

public void lightOff() {
    super.setFill(Color.BLACK);
}   

【问题讨论】:

    标签: java javafx decorator


    【解决方案1】:

    最简单的方法可能是将装饰器的所有相关属性绑定到底层对象:

    public PianoKeyDecorator(KeyView keyView) {
        this.keyView = keyView;
        fillProperty().bindBidirectional(keyView.fillProperty()); 
        // bind any other properties you wish to change. 
    }
    

    另一种方法可能是将键的视图部分与其逻辑完全分开,但这可能会迫使您对设计进行相当大的更改。

    编辑:
    想一想,我认为对于这个例子,strategy 设计模式可能比装饰器更适合,所以你只会改变声音的播放方式而不是整个键。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-28
      • 2015-07-25
      • 2019-02-27
      • 1970-01-01
      • 2013-08-22
      相关资源
      最近更新 更多