如何避免在课堂上有许多实例变量的getter / setter方法(How to avoid get

2019-09-01 04:16发布

我会尽力保持简短。

我有很多实例变量(30+),因此许多getter / setter方法的类。 通过自己的类很简单,但由于干将/ setter方法只是爆炸的LOC(有也是太多的代码口是心非)。

所以我删除的属性,并将它们存储在一张地图,这样

public class MyTechnicalToolClassX
{

//...constructor

private Map<String, Object> data;

public Object getAttributeByKey(AttributeKey key)
{
    // ...doStuff, check data associated with key, etc
    // if (predicate == true) return otherData;
    return data.get(key.toString());
}

public void setAttributeByKey(AttributeKey key, Object value) throws IllegalArgumentException
{
    if(key.getType().isInstance(value))
    {
        data.put(key.toString(), value);
    }
    else
    {
        throw IllegalArgumentException("The passed value has the wrong type, we expect: "
        + key.getType().getName());
    }
}

public enum AttributeKey
{
    someKey1("key1", String.class),
    someKey2("key2", Date.class),
    //...
    someKeyN("keyN", SomeType.class);

    private String key;
    private Class valueType;

AttributeKey(String key, Class valueType)
{
    this.key = key;
    this.valueType = valueType;
}

@Override
public String toString()
{
    return key;
}

public Class getType()
{
    return valueType;
}

} // AttributeKey

} // MyTechnicalToolClassX

AttributeKey曾经是只是一个字符串,但这样一来,我可以保证的setter类型安全。 现在我的问题,我删除了类中的代码口是心非,但我有其他类,也有很多属性(因为它们代表了技术的对象......),这里什么是最好的方法呢? 为了让每一个类自身的AttributeKey枚举?

我加了些心思。 我在编译的时候,现在的类型安全。 这里是我的getter和setter新的界面。

public <Type, SetVal extends Type> void setAttributeByName(IAttribute<Key, Type> attribute, SetVal value);

public <Type> Type getAttributeByName(IAttribute<Key, Type> attribute);

约书亚·布洛克把这种概念的类型安全的异构容器 。

Answer 1:

忘记告诉你是在OOP学校学到的东西!

我们已经在3年内走过了途径。 现在,我们有更好的语言。 斯威夫特,防锈,科特林,围棋等,我们理解数据/值类型和操纵它的代码之间的差异。 正确的企业架构CLEAN提倡这种在Java领域。 但Java只是不提供这种模式的语言级的支持。 最终的结果是大量使用的像RxJava(依然精彩)的东西,注释处理器是做代码生成等,但它真的很难感到幸福围绕Java的遗产拖动这些天。 科特林趋于解决办法的Java不能在一个非常非常小的价格Java的问题:严格的源兼容性的损失(这不是Groovy中)。

原来的答案,在底部更新。

有两个答案。

一:

没用的样板!

如果类代表一些大的数据对象,它听起来就像大多数成员变量是数据只是容器。 当这样的事情的话它不那么重要了严格遵循信息隐藏的面向对象编程惯例。 人们经常混淆本公约的宗旨和最终滥用它。 它仅仅是为防止从程序员不必处理的对象的复杂的和不必要的内部工作方式。 而不是掩模整个对象,只是掩盖不应该与被弄乱的部件。 在你只是从数据库的映射信息或者被用作储存容器的情况下,这样的代码:

import java.util.Date;

public class Article {

    protected int id;

    protected String guid;
    protected String title;
    protected String link;
    protected Date pubDate;
    protected String category;
    protected String description;
    protected String body;
    protected String comments;

    protected Article (String articleTitle, String articleBody) {
        title = articleTitle;
        body = articleBody;
    }

    protected Article (String guid, String articleTitle, String articleLink,
            long publicationDate, String category, String description,
            String articleBody, String commentsLink) {
        this(articleTitle, articleBody);
        this.guid = guid;
        this.link = articleLink;
        this.pubDate = new Date(publicationDate);
        this.category = category;
        this.description = description;
        this.comments = commentsLink;
    }

    protected Article (int id, String guid, String articleTitle, String articleLink,
            long publicationDate, String category, String description,
            String articleBody, String commentsLink) {
        this(guid, articleTitle, articleLink, publicationDate, 
                category, description, articleBody, commentsLink);
        this.id = id;
    }

    protected int getId() {
        return id;
    }

    protected String getTitle() {
        return title;
    }

    protected String getGuid() {
        return guid;
    }

    protected String getLink() {
        return link;
    }

    protected String getComments() {
        return comments;
    }

    protected String getCategory() {
        return category;
    }

    protected String getDescription() {
        return description;
    }

    protected String getBody() {
        return body;
    }

    protected void setId(int id) {
        this.id = id;
    }

    protected void setGuid(String guid) {
        this.guid = guid;
    }

    protected void setTitle(String title) {
        this.title = title;
    }

    protected void setLink(String link) {
        this.link = link;
    }

    protected void setPubDate(Date pubDate) {
        this.pubDate = pubDate;
    }

    protected void setCategory(String category) {
        this.category = category;
    }

    protected void setDescription(String description) {
        this.description = description;
    }

    protected void setBody(String body) {
        this.body = body;
    }

    protected void setComments(String comments) {
        this.comments = comments;
    }

}

..是完全恶劣。

在这样的情况下,我们实在没有理由去通过所有的额外的工作只是访问数据对象的成员。 特别是如果你只是使用它们的代码的一些外部线路:

public OtherClass {

    private Article article;

    public OtherClass(Article data) {
        article = data;
    }

    public String getArticleContents() {

        return (new StringBuilder())
        .append(article.getTitle())
        .append(article.getCategory())
        .append(dateToString(article.getPubDate())
        .append(article.getBody())
        .toString();
    }
}

只需直接访问成员,并保存自己几百行代码的(就像你建议你试图做)。

这导致了第二次回答这个问题..

二:

设计发臭..

您的代码可能会腐烂。 厨师拉姆齐是惭愧。 这是因为:

显然,上述OtherClass是完全无用的,因为它的功能可以(也应该)被放置在Article类,而不是包含在一些其他的,无用的,不需要的,文件系统乱抛垃圾OtherClass 。 如果你这样做,你可以约什需要getter和setter 忘记 OtherClass因为事情与它的接口可能只需要文章内容 ,而不是标题,正文等,分别。 在这种方法的Article类隐藏一切从外面的世界,只提供了绝对需要的信息。

由于这是两个完全可行的解答您的问题,必须有一个SOLUT 学家

使用Clojure的

模拟对象

虽然你可以使用闭包来模拟对象 ,甚至有更好的方法。 有趣的是,在把函数作为第一类公民的语言,你可以在传统的面向对象的范式完全使用地图模式 - 当你开始在你的30多名成员场类系统,您的重构弄清楚被给予。

与此相比,原Article + OtherClass方法:

(defn Article []
  (let [id (atom nil)
        guid  (atom nil)
        title  (atom nil)
        link (atom nil)
        pubdate (atom nil)
        category (atom nil)
        description (atom nil)
        body (atom nil)
        comments (atom nil)

        set (fn [g t l p cg d b cm]
              (do (reset! guid g)
                  (reset! title t)
                  (reset! link l)
                  (reset! pubdate p)
                  (reset! category cg)
                  (reset! description d)
                  (reset! body b)
                  (reset! commments cm)))
        get (fn [] [@guid
                    @link
                    @description
                    @comments
                    :content (content)])

        content #(str title category pubdate body)]
    {:get get, :set set}))

这上面examble是一个系统,由两个答案取点,并将它们组合成一个隐藏不需要的成员,采用了逻辑功能(该功能来获取“内容”),并使用不需要了难以置信的大量闪亮的样板的语言码..

更换类/对象系统

虽然这是怎样一个对象的函数式语言建模很好的例子,它不完全是地道到的Clojure和一般功能的编程。 为了更容易的方法来做到结构化数据,看的Clojure StructMaps和记录 。

2017年更新

只需使用科特林 。 它固化全线Java的疾病。 它有所有这些事情一流的语言支持和编译器甚至会帮助你摆脱无用的样板。 它存在了7年,在一个稳定的版本为自二月2016年如果我不得不原名吧,我可能就不会列入闭幕。



Answer 2:

也许你正在寻找的东西像Lambok 。



文章来源: How to avoid getters/setters in classes with many instance variables