How to restrict access to field setters of an object? Would achieving this with inheritance would be a bad choice?

Viewed 277

I have some business data objects that are created by the underlying services (say the data repository). These objects are created step by step. i.e (Step one only finds the image object from google, step two retrieves metadata about the image, step three downloads it to disk).

These same objects will be rendered in UI as they are being built. So the UI doesn't need to know anything about the setters and shouldn't have access to it.

But the services who are creating the instance, needs to have access to the setters. Please note that this model will be used from other packages so making setters package private is not a solution.

Here is the requirement in terms of code:
Image model:

class Image {
 private String src;
 public String getSrc(){
  return field;
 }
 public void setSrc(String src){
  return src;
 }
}

Service model:

interface IService {
 Image get(...);
 Image processMore(Image i);
}

UI/client code:

Image i = service.get(params);
render(i);
i = service.processMore(i);
render(i);
i.setSrc(null); //This is the problem. Client should not have access to this method.

Possible solutions:
Solution 1: Interfacing

public interface IImage{
 String getSrc();
}
interface IService {
     IImage get(...);
     IImage processMore(Image i);
    }
IImage i = service.get(params);
render(i);
i = service.processMore(i);//Casting IImage to Image - this cast can easily fail and no way to know IImage is always an Image
render(i);

Draw back: Casting issue as I have commented. Also a lot of boilerplate code will have to be written, for each object. This will get very complicated when Image model is extended.

Solution 2: Builder pattern
Again a lot of boilerplate code. But strictly speaking, Builder pattern does not fit here as the object is built in steps and we'll have to call getSrc() on a builder class, which probably violates something in the books.

Solution 3: Inheritance

public abstract class Image {
 protected String src;

 protected Image() {} //Ensure this class instance is never created
 public String getSrc(){
  return field;
 }
 protected void setSrc(String src){
  return src;
 }

 public static class Buildable extends Image {
  protected String src;

  public Buildable() {
   super();
  }

  @Override
  public void setSrc(String src){
   return src;
  }
 }
}

interface IService {
         Image get(...);
         Image processMore(Image.Buildable i);
        }
    Image i = service.get(params);
    render(i);
    i = service.processMore(i);//Casting Image to Image.Buildable - as Image constructor is protected and Image.Builder is public, only way to create Image is creating Image.Buildable and hence this cast should never fail.
    render(i);

So as a beginner who is learning SOLID principal, my question is,

  1. Does this inheritance model violates SOLID (or other clean code guidelines)? If so how it should be done?
0 Answers
Related