如何在不使用Java中的全局变量的情况下在两个类之间共享变量?

时间:2014-11-14 20:15:31

标签: java oop variables

假设我有两个对象LightLightSwitch我想要做的是

  

启用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

6 个答案:

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

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