简体   繁体   中英

Is placing all setters of derived class to util class a good design?

I read some codes like this:

public class Base {
    protected Map<String, Object> attrMap = new HashMap<>();
    public Map<String, Object> getAttrMap() {
        return this.attrMap;
    }
}

public class DerivedA extends Base{}

public class DerivedB extends Base{}

public class Util {
    public void setDerivedAAttrX(Base base, Object object) {
        base.getAttrMap().put("DERIVEDA_X", object);
    }
    public void setDerivedAAttrY(Base base, Object object) {
        base.getAttrMap().put("DERIVEDA_Y", object);
    }
    public void setDerivedBAttrX(Base base, Object object) {
        base.getAttrMap().put("DERIVEDB_X", object);
    }
    public void setDerivedAttrZ(Base base, Object object) {
        base.getAttrMap().put("DERIVED_Z", object);
    }
}

I asked the implementor of those codes why design like this, here is his answer:

  1. We can't let those setters in Base , because it's set derived attributes.
  2. If we move those setters to corresponding derived class, it's hard to handle setDerivedAttrZ .(Note that it can set attribute Z for both DerivedA and DerivedB )we may have a Base reference and we will set attribute Z. We know it's DerivedA or DerivedB indeed, but don't know it's which one exactly. So we can't cast it to derived class and call derived setters.
  3. Since place these setters in Base or derived class both have some shortcomings, he comes to a Util class to handle those setters.

So my question, is it a good design for that case?

I think it is bad design. The basic of object-oriented programming is to call methods on objects, and not helper functions to which objects and method parameters are passed.

Guess. This reeks of several classes having miscellaneous capabilities, some shared. And untyped at that.

An improvement would be to use an interface with capability and use that as key.

public class Base {
    private Map<Class<?>, Object> attrMap = new HashMap<>();

    protected <T> void add(Class<T> clazz, T object);

    /** @return null when not available. */
    public <T> T lookup(Class<T> clazz) {
        Object object = attrMap.get(clazz);
        return clazz.cast(object);
    }
}

For the lookup one could use Optional<T> instead of a null result.

About the original:

The string constants and aggregation might be too much boiler code, circumstantial coding.

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