2014-11-14 241 views
0

假设我有两个对象LightLightSwitch我想做的事是如何共享两个类之间变量没有在Java中使用全局变量?

接通LightSwitch然后检查Light是打开或关闭(在这种情况下,预期的答案是“上”)

注意的是,当开关被接通时该共享变量名current将设置为true然后Light也将开启

我感兴趣的这个问题是:

  • 如何两个类(在这种情况下是LightLightSwitch)可以在不使用全局变量(在这种情况下,共享变量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

听起来像经典的观察者设计模式可以适应这里。 – Avi 2014-11-14 20:23:05

+0

你是什么意思“全局变量”?你的意思是静态变量? – Loc 2014-11-14 20:26:22

+0

@LocHa是的,有点像'公共静态...' – fronthem 2014-11-14 20:30:03

回答

4

有2种方法。

更具体的做法

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可能是一个非常不错的选择更多的东西通用的,它实际上是扩展了我之前给的例子。如果你不熟悉它,这是实现事件的一种方式,因此在两个物体的状态之间保持联系,而当一个物体发生变化时,另一个物体“观察”这种变化并作出相应的反应。在这种情况下,你的光线会观察开关。

2

有几个选择,虽然在一般情况下,这个优雅的解决方案是完全不使用全局变量,不得私自使用它们:)

Singleton模式

让单身LightState或什么 - 让它的构造PRIVA在工厂类中返回单个静态光源状态。然后,每当有人要求“lightstate”,他们将给予相同的值

静态变量

只是做一个静态的(私人,吸气剂)变量在这两个类中的一个,并有另一个请求它。

Observer模式

应用其他两种方法之一,但留在国家的负担,通知正确的代理时的状态的变化;这样,代理不负责链接到状态,这使链接更简单和更优雅。

替代地,观察者可以通知控制器剂,这将随后用任何操作需要发生,这意味着两个独立的元件可以保持完全不知道的共享信息采取相应的行动。

继承

轻LightSwitch中的一个子类,或者反之亦然?它依赖于使用情况,但可能不是。但是,如果是这样,您可以创建一个可以访问的受保护的静态变量。通过使“最终”包装对象的这种状态下,你会确保每nobobdy切换出来,导致混乱的错误引用

直接联系

有LightSwitch的跟踪光。您仍然想知道灯的状态何时从开关以外的某种方式改变,因此观察者模式仍然可以派上用场。

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 
1

最基本的答案是,在OOP你不同意这样的变量。 OOP(以及其他模块化编程范例)的要点之一是封装。可以根据公共接口如何指定它可以修改或查询对象。要修改对象的状态或更改其行为,必须调用属于该对象的方法之一。这样,目标就完全控制着自己的状态;它知道何时调用它自己的方法,并且这些方法本身能够修改对象的状态信息。

拥有一个共享变量会毁掉所有这一切。如果一个变量在两个对象之间共享,那么当一个对象分配给变量时,它可以以另一个对象无法控制的方式修改另一个对象的行为。所以这是要避免的。

相反,其中一个对象需要调用另一个对象的方法。如果您的LightSwitchturnOn方法很可能需要打开Light。最直接的方式做到这一点,我认为,就是要告诉LightSwitch在其构造它会变成什么Light上:

public LightSwitch (Light light) { ... } 

,或者如果它控制一个以上的光,

public LightSwitch(Light[] light) { ... } // or use a List or Set or whatever 

然后,构造函数将保存该引用,然后其turnOn方法将调用light.turnOn()。这就是你如何在OOP中处理这个问题,而不是使用共享变量。

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()); 
} 

这是更面向对象,不需要任何全局变量。

+0

@Arkadity谢谢你的回答你在OOP课上学到了什么,但我只是觉得如何才能生活在没有任何意义的开关中。这个案例研究我只关注两个完全独立的类,但他们可以互相分享变量。问题是如何? – fronthem 2014-11-14 21:05:23

+0

@ terces907:我的解决方案将解决您的问题:灯和开关之间完全独立。 – Loc 2014-11-14 21:10:11

+1

灯不“居住”开关。开关是“意识到”光。开关必须切换一些东西,对吧? (实际上,你需要一个可切换的界面)。术语是“组合”(不是我们这里所拥有的)和“定向联系”(我们在这里有)。 – Arkadiy 2014-11-14 21:16:05

2

查看我的解决方案如果您想要在LightSwitch & Light之间解除耦合。您可以轻松地添加/删除灯之间的联系,并切换

灯类:

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 
    } 
相关问题