简体   繁体   中英

Design pattern: Save private members

Say we have a class Potato (and instances therefore) that has an attribute smoothness which is used for other method but is not pretended to be public. This attribute is setted when the instance is created and is used only internally the instance.

Moreover, my system should support several database drivers, therefore I have an interface "databse adaptor" that will be instantiated with the class which uses the driver I want to use at the moment.

Now comes the problem. I need to make the object(the potato) persistent and save it into a database, therefore I should save the smoothness of our potato by using the database adaptor class, but.. it's private? How can I send the smoothness of the potato without making it accessible for other purposes?

Thanks in advance

Write a method that allows the object to save itself, taking a writer of some kind as a parameter. Since this is a database, you might need to have both Insert and Update methods, instead of just a Save method. You might put these into an interface as well.

rough example:

public interface IDatabaseSaveable
{
   void InsertToDatabase(Database pDatabase);
   void UpdateDatabase(Database pDatabase);
}

public class Potato : IDatabaseSaveable
{
   private int mID;
   private double mSmoothness;

   public void InsertToDatabase(Database pDatabase)
   {
      pDatabase.InsertToPotatoes(mID, mSmoothness, ...);
   }

   public void UpdateDatabase(Database pDatabase)
   {
      pDatabase.UpdatePotatoes(mID, mSmoothness, ...);
   }
}

You can create an importer/exporter interface pair that externalize the "state" of the Potato without giving access to its implementation details (in this case, its private members and data types). They are types of builders.

public class Potato {
  public interface IExporter {
    void AddSmoothness(string value);
  }
  public interface IImporter {
    string ProvideSmoothness();
  }

  public Potato(IImporter importer) {
    this.smoothness = int.Parse(importer.ProvideSmoothness());
  }

  public void Export(IExporter exporter) {
    exporter.AddSmoothness(this.smoothness.ToString());
  }

  public Potato(int smoothness) {
    this.smoothness = smoothness;
  }

  private int smoothness;
}

Then, your database adapter classes will implement the relevant interfaces and use the corresponding methods. Look here for the original idea.

This is a variation on having a smoothness property marked as internal . Assuming that potato must have a smoothness set before you can use it, an internal constructor might be better. I'm going to accept on faith that there's a good reason to hide smoothness. Modesty on the part of the potato, perhaps?

public class Potato
{
    internal int Smoothness { get; set; }

    internal Potato(int smoothness)
    {
        this.Smoothness = smoothness;
    }
    private Potato() { }
}

Only classes in the same assembly will be able to instantiate a Potato using the internal constructor. And only classes in the same assembly will be able to access Smoothness (so they can save the potato.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM