Electronic Components in Java I've been watching digital technology in the last few days. This has aroused my interest. I would like to realize a program that simulates basic components of circuit technology and their functions. I have developed a small approach on how to implement the elements of circuit technology on an object-oriented level. Is that a good way of thinking, with which you can continue working? Or could one formulate the building blocks more elegantly in code?

Output.java

/* objects of classes that implement this interface can be used as signaler */

public interface Output {
    public boolean getOutput();
}


Signal.java

public class Signal implements Output {
    private boolean signal;

    public Signal(boolean value) {
        setSignal(value);
    }

    public void setSignal(boolean value) {
        signal = value;
    }

    public boolean getOutput() {
        return signal;
    }
}


LinkingElements.java

abstract public class LinkingElement {
    Output signal1;
    Output signal2;

    public LinkingElement(Output signal1, Output signal2) { 
        this.signal1 = signal1;
        this.signal2 = signal2;
    }
}


And.java

public class And extends LinkingElement implements Output {
    public And(Output signal1, Output signal2) { 
        super(signal1, signal2);
    }

    public boolean getOutput() {
        return signal1.getOutput() &amp;&amp; signal2.getOutput();
    }
}


Or.java

public class Or extends LinkingElement implements Output {
    public Or(Output signal1, Output signal2) {
        super(signal1, signal2);
    }

    public boolean getOutput() {
        return signal1.getOutput() || signal2.getOutput();
    }
}


LightBulb.java

public class LightBulb {
    private Output signal;

    public LightBulb(Output signal) {
        this.signal = signal;
    }

    public void isActive() {
        if(signal.getOutput()) {
            System.out.println("The lightbulb is shining.");
        } else {
            System.out.println("The lightbulb is switched off.");
        }
    }
}


Main.java

This class is just for testing:

public class Main {
    public static void main(String[] args) {
        Signal s1 = new Signal(true);
        Signal s2 = new Signal(true);
        Signal s3 = new Signal(true);
        Signal s4 = new Signal(false);
        And a1 = new And(s1, s2);
        Or a2 = new Or(s3, s4);
        And a3 = new And(a1, a2);
        LightBulb lightBulb = new LightBulb(a3);
        lightBulb.isActive();
    }
}
Thanks for sharing your code.

What you posted is a nice data structure.

But OOP is about behavior. (we still need data structures to store state but usually objects have behavior.

Let see is this way: There are 3 Types of component in an electronic system:


signal source (such as switches and sensors)
signal receivers (such as Light bulbs, LEDs or electric engines)
logical elements (such as And, OR NOT).


The signals are no objects (with behavior since they are just messages transfered between the objects... 

So I'd suggest classes like this:

// signal are still data structure
enum Signal { OFF, ON }

// some interfaces for abstraction
interface SignalReceiver {
    void consume(Signal signal, SignalSource from);
}
interface SignalSource {
    void triggers(SignalReceiver r);
}
interface LogicElement extends SignalReceiver, SignalSource {}




// a switch is a typica "signalSource"
class Switch implements SignalSource {
    private final Collection&lt;SignalReceiver&gt; receivers = new HashSet&lt;&gt;();
    private Signal state = Signal.OFF;
    private final String name;

    public Switch(String name) {
        super();
        this.name = name;
    }

    @Override
    public void triggers(SignalReceiver r) {
        receivers.add(r);
    }

    public void doSwitch() {
        state = Signal.values()[1 - state.ordinal()]; // get the other signal
        System.out.print("Switch "+name+" is "+state +" ");
        for (SignalReceiver signalReceiver : receivers) {
            signalReceiver.consume(state, this);
        }
    }
}




class LightBulb implements SignalReceiver {
    public LightBulb(SignalSource signalSource) {
        signalSource.triggers(this); // tells the source "trigger me!"
    }

    @Override
    public void consume(Signal signal, SignalSource from) {
        System.out.println("light is " + signal);
    }
}




class Or implements LogicElement {
    private final Collection&lt;SignalReceiver&gt; receivers = new HashSet&lt;&gt;();
    private final Map&lt;SignalSource, Signal&gt; inputs = new HashMap&lt;&gt;();

    Or(SignalSource... signalSources) { // "vararg" parameter, accepts many sources
        for (SignalSource signalSource : signalSources) {
            signalSource.triggers(this); // tells the source "trigger me!"
            inputs.put(signalSource, Signal.OFF);
        }
    }

    @Override
    public void triggers(SignalReceiver r) {
        receivers.add(r);
    }

    @Override
    public void consume(Signal signal, SignalSource from) {
        inputs.put(from, signal);
        Signal output = inputs.values().stream() // Java8 functional programming
                .max((s1, s2) -&gt; s1.compareTo(s2))// depends on order in enum!
                .get();
        for (SignalReceiver signalReceiver : receivers) {
            signalReceiver.consume(output, this);
        }
    }
}


And this is the test:

public class Electronics {
    public static void main(String[] args) {
        // circuit configuration
        Switch s1 = new Switch("left");
        Switch s2 = new Switch("right");
        new LightBulb(new Or(s1, s2));

        // operation        
        s1.doSwitch(); // light on
        s1.doSwitch(); // light off
        s2.doSwitch(); // light on
        s1.doSwitch(); // light on
        s2.doSwitch(); // light on
        s1.doSwitch(); // light off
    }
}


Yo may notice that I my approach has no "getter" method.
This is because "getter" as well as "setter" violate one of the most important OO principles: information hiding / encapsulation. You should avoid them on classes implementing actual behavior (on pure data objects they are OK...) The "rule of thumb" is: "Tell!, don't ask!"