我试图应用装饰器模式,但到目前为止,我遇到麻烦让它按照我想要的方式工作。
基本上我试图创建一个钢琴应用程序,它有一个扩展JavaFX矩形的钢琴键超类和两个子类白键和黑键,当你将鼠标悬停在它们上面时,这两个子类都有方法实现。
他们工作正常,但我现在正在尝试创建将覆盖超类的装饰者类'通过提供自己的播放方法并为该装饰器附加音频文件的相关字符串来播放方法。 例如PianoKeyViolinDecorator将追加"小提琴"在播放之前到音频文件名的末尾。
播放方法有效,但悬停在矩形上的方法不起作用。除非我在装饰器中设置高度和宽度,否则矩形不会出现在我的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);
}
答案 0 :(得分:1)
最简单的方法可能是将装饰器的所有相关属性绑定到底层对象:
public PianoKeyDecorator(KeyView keyView) {
this.keyView = keyView;
fillProperty().bindBidirectional(keyView.fillProperty());
// bind any other properties you wish to change.
}
另一种方法可能是将键的视图部分与逻辑完全分开,但这可能会迫使您更改设计。
编辑:
想想看,我认为在这个例子中strategy设计模式可能比装饰器更合适,所以你只会改变播放声音的方式而不是整个键。