Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The Object-Oriented way to separate the model from its representation

Tags:

oop

Suppose we have an object that represents the configuration of a piece of hardware. For the sake of argument, a temperature controller (TempController). It contains one property, the setpoint temperature.

I need to save this configuration to a file for use in some other device. The file format (FormatA) is set in stone. I don't want the TempController object to know about the file format... it's just not relevant to that object. So I make another object, "FormatAExporter", that transforms the TempController into the desired output.

A year later we make a new temperature controller, let's call it "AdvancedTempController", that not only has a setpoint but also has rate control, meaning one or two more properties. A new file format is also invented to store those properties... let's call it FormatB.

Both file formats are capable of representing both devices ( assume AdvancedTempController has reasonable defaults if it lacks settings ).

So here is the problem: Without using 'isa' or some other "cheating" way to figure out what type of object I have, how can FormatBExporter handle both cases?

My first instinct is to have a method in each temperature controller that can provide a customer exporter for that class, e.g., TempController.getExporter() and AdvancedTempController.getExporter(). This doesn't support multiple file formats well.

The only other approach that springs to mind is to have a method in each temperature controller that returns a list of properties and their values, and then the formatter can decide how to output those. It'd work, but that seems convoluted.

UPDATE: Upon further work, that latter approach doesn't really work well. If all your types are simple it might, but if your properties are Objects then you end up just pushing the problem down a level... you are forced to return a pair of String,Object values, and the exporter will have to know what the Objects actually are to make use of them. So it just pushes the problem to another level.

Are there any suggestions for how I might keep this flexible?

like image 541
Chris Arguin Avatar asked Jul 08 '09 05:07

Chris Arguin


People also ask

What is object-oriented representation?

Idea behind Object Oriented Systems of Knowledge Representation: ADVERTISEMENTS: The basic idea behind an OOS is the notion of classes of objects interacting with each other to accomplish some set of tasks. The objects have well defined behaviours. They interact with each other through use of messages.

What is object-oriented process model?

The object-oriented modeling approach creates the union of the application and database development and transforms it into a unified data model and language environment. Object-oriented modeling allows for object identification and communication while supporting data abstraction, inheritance and encapsulation.

Which methods are used for object-oriented?

There are three main types of methods: interface methods, constructor methods, and implementation methods. Most beginner programmers are familiar with implementation methods. For example, in Python, appending to a list takes a method append and applies it to a list object.

What are the 4 basic concepts of object-oriented programming?

The main ideas behind Java's Object-Oriented Programming, OOP concepts include abstraction, encapsulation, inheritance and polymorphism.


1 Answers

What you can do is let the TempControllers be responsible for persisting itself using a generic archiver.

class TempController 
{
    private Temperature _setPoint;
    public Temperature SetPoint { get; set;}

    public ImportFrom(Archive archive)
    {
        SetPoint = archive.Read("SetPoint");
    }
    public ExportTo(Archive archive)

    {
        archive.Write("SetPoint", SetPoint);
    }
}

class AdvancedTempController
{
    private Temperature _setPoint;
    private Rate _rateControl;
    public Temperature SetPoint { get; set;}
    public Rate RateControl { get; set;}

    public ImportFrom(Archive archive)
    {
        SetPoint = archive.Read("SetPoint");
        RateControl = archive.ReadWithDefault("RateControl", Rate.Zero);
    }

    public ExportTo(Archive archive)
    {
        archive.Write("SetPoint", SetPoint);
        archive.Write("RateControl", RateControl);
    }
}

By keeping it this way, the controllers do not care how the actual values are stored but you are still keeping the internals of the object well encapsulated.

Now you can define an abstract Archive class that all archive classes can implement.

abstract class Archive
{
    public abstract object Read(string key);
    public abstract object ReadWithDefault(string key, object defaultValue);
    public abstract void Write(string key);
}

FormatA archiver can do it one way, and FormatB archive can do it another.

class FormatAArchive : Archive
{
    public object Read(string key)
    {
        // read stuff 
    }

    public object ReadWithDefault(string key, object defaultValue)
    {
        // if store contains key, read stuff
        // else return default value
    }

    public void Write(string key)
    {
        // write stuff
    }
}

class FormatBArchive : Archive
{
    public object Read(string key)
    {
        // read stuff
    }

    public object ReadWithDefault(string key, object defaultValue)
    {
        // if store contains key, read stuff
        // else return default value
    }

    public void Write(string key)
    {
        // write stuff
    }
}

You can add in another Controller type and pass it whatever formatter. You can also create another formatter and pass it to whichever controller.

like image 174
jop Avatar answered Sep 28 '22 22:09

jop