OOP design : Car - Connection between Tank and Engine
Asked Answered
D

4

7

I'm not sure whether I'm violating OOP conepts insanely.

Say there is a Carclass which "has" an Engine and a Tank.

When the Engine is operating , it will take oil from the Tank (say unit by unit per a cycle though oil is uncountable)

How should the Engine get Oil from the Tank ? (When both are fields of Car?)

Actually an Engine should be continually " Supplied" oil rather than "gets" oil.
There should be "OilCirculatingSystem" which gets Oil from the Tank
and supplies to Engine.
How can I model this system in classes ?
Is there a suitable Design Pattern? enter image description here

** * Edit : Simply ,how to have an "Flow of Oil" from Tank to Engine ? (Is it Oil's responsibility to flow from the Tank to Engine when a valve is opened ?

Docent answered 22/10, 2011 at 16:2 Comment(2)
My understanding of car engines may be flawed, but isn't the oil tank a part of the whole engine assembly?Decidua
Unrelated to your question but important I think: checkEngineOil doesn't really convey what you are using it for. You are really saying, if I have enough oil to start. I'd suggest something along the lines of if (tank.oilLevel() > OIL_NEEDED_TO_START_ENGINE).Nuno
P
4

I'm sorry if it fries the brain. Implementation of methods is missing but you get the idea I hope.

class Tank
{
    Oil oil;

    public Tank(OilPipe pipe)
    {
        pipe.OilNeeded += new EventHandler<OilNeededEventArgs>(pipe_OilNeeded);
    }

    public void FillOil(Oil oil) { }

    void pipe_OilNeeded(object sender, OilNeededEventArgs e)
    {
        e.Oil = oil.SubtractLiters(5);
    }
}

class OilPipe
{
    public event EventHandler<OilNeededEventArgs> OilNeeded;

    public Oil SuckOil();
}

class Piston
{
    public void Move() { }
}

class Oil
{
    public Energy Burn() { }
}

class Energy
{
    public void Push(Piston piston) { }
}

class Engine
{
    OilPipe oilPipe;

    public Engine(OilPipe oilPipe, Piston piston)
    {
        this.oilPipe = oilPipe;
    }

    public void MovePiston()
    {
        Oil oil = oilPipe.SuckOil();
        Energy energy = Burn(oil);
        energy.Push(piston);
    }
}

class Car
{
    Engine engine;

    public Car(Engine engine, Tank tank)
    {

    }

    public void Accelerate()
    {            
         engine.MovePiston();
    }
}
Prohibition answered 22/10, 2011 at 16:26 Comment(2)
Ok.I got the idea except "When does the pipe_OilNeeded event occur".It should be when SuckOil() right? .Events are hard to understand.I'll read this answer about events several more times and try to understand.Docent
@D-Shan Yes when SuckOil is called, the class fires the event asking the source to provide oil.Prohibition
C
3

Car analogies are never perfect, because cars and engines are actually very complex systems. You have to ignore a lot of things to model them simply. Your problem is that you don't seem to understand how an engine works in the first place.

The oil pan is part of the engine, not the car. The gas tank is part of the car, but not the engine. You have an oil pump (also part of the engine) that pumps oil into the cylinders of the engine. Most cars (maybe all) don't "check the oil level" and refuse to start. The engine will simply seize if it doesn't get enough oil. Likewise, if it doesn't get enough gas, it doesn't check the gas tank level.. it just runs out of fuel.

It would be more like this:

class Car
{
    Engine engine;
    GasTank gasTank;

    StartEngine() { engine.Start(); }
}

class Engine
{
    Timer timer;
    OilPan oilPan;
    OilPump oilPump;
    public Engine() { oilPump = new OilPump(oilPan, this); }
    Start() { timer.Start(oilPump); }
    InjectOil() {}
}

class Timer
{
    OilPump op; // This is a reference
    public Timer(OilPump op) { _op = op; }
    Revolve() { op.Pump(); }
}
class OilPump {
    OilPan _oilPan; // Reference
    Engine _engine; // Reference

    OilPump(OilPan oilPan, Engine engine) { _oilPan = oilPan; _engine = engine; }
    Pump() { _engine.InjectOil(_oilPan.GetOil); }
}

The timer reprsents the revolution of the engine, as it revolves, it actuates the oil pump which pumps oil into the cylinders. Oil is not typically "consumed", like fuel. It is recycled. It can break down over time, and in some engines that are in bad shape, it can burn.

The Oil Pump reference represents a mechanical linkage between the engine and the oil pump (typically gears turn it). The Timer does not have an oil pump, it has a reference to an oil pump.

The gas tank would work in a similar fashion.

Again, this is all imperfect (very imperfect), because there is so much missing.

Cynarra answered 22/10, 2011 at 16:47 Comment(0)
S
2

I would say that the Car itself is the OilCirculatingSystem.

class Car
{
   Tank tank;
   Engine engine;
   start()
   {
   //whatever
   }
   feedEngine()
   {
      while ( tank.hasOil() )
      {
          tank.getOil();
          engine.giveOil();
      }
   }
}

The Car itself is already the the class connecting all your components together, why would you need another one?

Scully answered 22/10, 2011 at 16:8 Comment(3)
Ok.It makes sense.Can we have like after the Car "initiates" a connection between Engine and Tank , Engine have access to the Tank and directly get's oil from Tank and Car doesn't need to do it for the Engine.Docent
@D-Shan as I see it, that would violate the principles of loose coupling (look that up). There's no reason for tank and engine to have a connection. They should contain their own logics and nothing more. An engine can be fed by gas directly from the pump, not necesarilly from the tank. The tank doesn't necesarilly have to feed an engine. So why connect them? Good OOP means classes are loosely coupled and contain their own logic. This logic belongs in car, as basically that's what a car is - a means for different components to interact with each other.Scully
What I'm confused with is the behavior of oil.Actually Oil "flows" from the Tank to Engine rather than someone "carries" the oil from Tank to EngineDocent
A
1

The fact that the supply is continuous means that it will have to be checked after a specified time interval. If this is not what you are looking for, you may have to clarify your question.

The most logical approach to this problem (assuming you dont have event-based or signal/slot programming) would to have the car check the state of the engine, every time interval of your choice, and if the engine needs more oil, the car should read some data from the tank and pass it to the engine.

Here is a simple pseudocode example to demonstrate what I mean:

class Engine
{
    void start()
    {
        while(true)
        {
            // do engine stuff here
        }
    }

    void getOil(int amount)
    {
        // do stuff with oil
    }
}

class Tank
{
    int oilAmount
    boolean hasOil

    int giveOil()
    {
        return oilAmount
    }
}

class Car
{
    Tank tank
    Engine engine

    void start()
    {
        engine.start()
        while(true)
        {
            engine.getOil(tank.giveOil())
            sleep(100)
        }
    }
}
Aldose answered 22/10, 2011 at 16:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.