Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.2k views
in Technique[技术] by (71.8m points)

java - Builder pattern vs encapsulation of a data

How should I retain Encapsulation Principle of OOP, when using builder pattern? I mean fact that builder should provide abstraction layer between object and the code that uses it, so that it can be constructed part-by-part, requires either making setter for every parameter of an object that we would normally pass in the constructor. That again may be undesirable in some cases, as I don't want client to be able to modify value that I have to via builder. Example to picture what I mean is below:

public class Cat
{
    private string _race;
    private string _name;
    public Cat()
    {
         _race = "common";
         _name = string.Empty;
    }
    public void setRace(string race) { _race = race; }
    public void setName(string name) { _name = name; }
}

public class CatBuilder
{
    private Cat _objectUnderConstruction;
    public CatBuilder() { _objectUnderConstruction = new Cat(); }
    public CatBuilder WithName(string name)
    {
         _objectUnderConstruction.setName(name);
         return this;
    }
    public CatBuilder OfRace(string race)
    {
         _objectUnderConstruction.setRace(race);
         return this;
    }

}

This is not production code, I wrote it now with presentation in mind, so do not get mad on how it is constructed.

In the example above there is need to set cat's race, as we need that information for the purpose of object filling, so we need to pass info into it. At the same time I don't want anyone to ever change race of my cat during its lifetime (e.g. it would change from egyptian to british in the middle of processing) Normally I would get rid of accessor method, but I need for the builder. This way, encapsulation of data is hurt (because straight get and set aren't encapsulating anything), and I want to avoid it.

This example is simple and I could pass parameter in constructor, but imagine bigger class, where there is a lot of such fields, what in this case? Should I pass some configuration object inside (which is almost like builder, but simpler, hence builder is pointless) or pass the builder itself to the constructor (which is weird, but what do I know)?

How I should do that?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If your builder is tightly-coupled with your class you can make Builder subclass of the object being constructed:

public class Cat
{
    private string _race;
    private string _name;
    public Cat()
    {
         _race = "common";
         _name = string.Empty;
    }
    private void setRace(string race) { _race = race; }
    private void setName(string name) { _name = name; }

    public class Builder
    {
         private Cat _objectUnderConstruction;
         public CatBuilder() { _objectUnderConstruction = new Cat(); }
         public CatBuilder WithName(string name)
         {
             _objectUnderConstruction.setName(name);
             return this;
         }
         public CatBuilder OfRace(string race)
         {  
             _objectUnderConstruction.setRace(race);
             return this;
         }
    }
}

This way, you'll be able in Builder to access private fields and methods of Cat and use it like new Cat.Builder().OfRace("").OfName("").Build().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...