假设我有两个对象Light
和LightSwitch
我想要做的是
启用
LightSwitch
,然后检查Light
是开启还是关闭(在这种情况下,预期答案为“开启”)
请注意,当启用开关时,共享变量名称current
将设置为true
,然后Light
也会启用
我对这个问题感兴趣的是:
Light
和LightSwitch
)如何在不使用全局变量的情况下共享变量值(在这种情况下,共享变量为current
)?预期输出(或者只是你喜欢的另一个输出可以告诉我好,灯打开/关闭):
switch on: true // This line just set variable `current` in `LightSwitch` class
Light is turned on // This line just check that `current` variable in `Light` class is True or false
switch on: false
Light is turned off
答案 0 :(得分:4)
有两种方法。
更具体的方法
public class Light implements Switchable{
private boolean on;
@Override
public boolean isOn() { return on; }
@Override
public void setIsOn(boolean on) { this.on = on; }
}
public class LightSwitch {
public void List<Switchable> switchables = new ArrayList<Switchable>(); // A generic list of things that are controlled by the switch. Doesn't have to be lights.
public void off() { setState(false); }
public void on() { setState(true); }
private void setState(boolean state) {
for(Switchable switchable: switchables) {
switchable.setIsOn(state);
}
}
}
观察者方法
observer design pattern可能非常适合更通用的东西,它实际上扩展了我之前给出的例子。如果你不熟悉它,那么它就是一种实现事件的方式,从而在两个对象的状态之间建立起来,而当一个对象被改变时,另一个对象就是#34;观察&#34;这会改变并做出相应的反应。在这种情况下,您的灯会观察开关。
答案 1 :(得分:2)
有一些选项,但总的来说,这个优雅的解决方案根本不是使用全局变量,而是秘密使用它们:)
单身人士模式
制作单例LightState或其他 - 在工厂类中使其构造函数为私有,在请求时返回单个静态lightstate。然后,每当有人请求&#34; lightstate&#34;时,他们将获得相同的值
静态变量
只需在两个类中的一个中创建一个静态(私有,带有getter)变量,然后另一个请求它。
观察员模式
应用其他两种方法中的一种,但在状态发生变化时,请将状态负担留给通知正确的代理;这样,代理不负责链接到状态,这使链接更简单,更优雅。
或者,观察者可以通知控制器代理,然后控制器代理将采取相应的行动,无需采取任何行动,这意味着两个独立的元素可以完全不知道共享信息。
<强>继承强>
Light是Lightwitch的子类,反之亦然?它的使用依赖,但可能不依赖。但是,如果是这样,您可以创建一个可以访问的受保护静态变量。制作一个&#34; final&#34;对于这种状态的包装器对象,你确保每次切换它都会导致混淆错误引用
直接关联
让lightswitch跟踪灯光。你仍然想知道光的状态何时从开关以外的某些方式改变,所以观察者模式仍然可以派上用场。
答案 2 :(得分:2)
通常,每LightSwitch
个连接到一个(或多个)Light
(s)。我首先将Light
实例传递给LightSwitch
(并将其保留为切换中的字段)。
private Light current;
public LightSwitch(Light light) {
this.current = light;
on();
}
public boolean isOn() {
return current.isOn();
}
public void on() {
current.setOn(true);
}
public void off() {
current.setOn(false);
}
public String toString() {
return isOn() ? "switched on" : "switched off";
}
然后你的main()
看起来像,
LightSwitch switch = new LightSwtich(new Light());
System.out.println("Light is: %s%n", switch);
switch.off();
System.out.println("Light is: %s%n", switch);
输出
Light is: switched on
Light is: switched off
答案 3 :(得分:2)
查看我的解决方案如果您想在LightSwitch&amp; amp;光。您可以轻松添加/删除灯光和开关之间的链接
光级:
public class Light {
private boolean on;
public void setOn(boolean on) {
this.on = on;
}
public boolean isOn() {
return on;
}
}
LightSwitch类:
public class LightSwitch {
private boolean on;
private Map<String, SwitchListener> listeners = new HashMap<String, SwitchListener>();
public void switchState() {
on = !on;
SwitchEvent event = new SwitchEvent(on);
for (SwitchListener switchListener : listeners.values()) {
switchListener.switchPerformed(event);
}
}
public void addListener(String id, SwitchListener listener) {
listeners.put(id, listener);
}
public void removeListener(String id) {
listeners.remove(id);
}
}
SwitchEvent类:
public class SwitchEvent {
private boolean on;
public SwitchEvent(boolean on) {
this.on = on;
}
public boolean isOn() {
return on;
}
}
SwitchListener类:
public interface SwitchListener {
void switchPerformed(SwitchEvent event);
}
使用示例:
public static void main(String[] args) {
LightSwitch lightSwitch = new LightSwitch();
final Light light1 = new Light();
final Light light2 = new Light();
lightSwitch.addListener("light1", new SwitchListener() {
@Override
public void switchPerformed(SwitchEvent event) {
light1.setOn(event.isOn());
}
});
lightSwitch.addListener("light2", new SwitchListener() {
@Override
public void switchPerformed(SwitchEvent event) {
// Example: light 1 on, light 2 off -- light 1 off, light 2 on
light2.setOn(!event.isOn());
}
});
// Test switch
lightSwitch.switchState(); // light 1 ON, light 2 OFF
lightSwitch.switchState(); // light 1 OFF, light 2 ON
}
答案 4 :(得分:1)
基本答案是,在OOP中你不能像这样分享变量。 OOP(以及其他模块化编程范例)的一个要点是封装。可以根据公共接口指定的对象来修改或查询对象。要修改对象的状态或更改其行为,您必须调用属于该对象的方法之一。这样,对象就完全控制了自己的状态;它知道何时调用自己的方法,并且仅这些方法就能够修改对象的状态信息。
拥有共享变量会破坏所有这些。如果变量在两个对象之间共享,那么当一个对象分配给变量时,它可以以另一个对象无法控制的方式修改另一个对象的行为。所以这是要避免的事情。
相反,其中一个对象需要调用另一个对象的方法。最有可能的是,如果您的turnOn
采用LightSwitch
方法,则需要启用Light
。我认为,最直接的方法是告诉LightSwitch
在其构造函数中它将启用Light
:
public LightSwitch (Light light) { ... }
或者,如果它控制多个灯光,
public LightSwitch(Light[] light) { ... } // or use a List or Set or whatever
然后构造函数将保存此引用,然后其turnOn
方法将调用light.turnOn()
。这就是你如何在OOP中处理这个问题,而不是使用共享变量。
答案 5 :(得分:1)
任何教你的人都会给你一些坏习惯,这些习惯会使你的Java编程(以及一般的OOP)变得困难。
您需要更好的封装。
的内容class Light {
...
public void startCurrent(){...};
public void stopCurrent(){...};
public boolean isOn();
}
class Switch {
Ligh target;
public Switch(Ligh target) {...}
public clickOn(){target.startCurrent();}
public clickOff(){target.stopCurrent();}
}
// now wire it all together
public static void main(String argv) {
Light light = new Light();
Switch switch = new Switch(light);
System.out.println("Light is on: " + light.isOn());
switch.clickOn();
System.out.println("Light is on: " + light.isOn());
switch.clickOff();
System.out.println("Light is on: " + light.isOn());
}
这更加面向对象,不需要任何全局变量。