代码之家  ›  专栏  ›  技术社区  ›  TheLQ

作为数据存储类的javabean设计是否糟糕?

  •  11
  • TheLQ  · 技术社区  · 15 年前

    通常JavaPractices.com是一个有好主意的好网站,但这个让我很困扰: JavaBeans are bad

    文章列举了几个原因,主要是JavaBean这个术语的意思是“JavaBean是一个可重用的软件组件,可以在生成器工具中进行可视化操作”,而不是数据存储,违反了某些模式,而且更为复杂。

    new MappedObject("column1", "column2", "yet another column", "this is stupid");

    除了数据库映射之外,我还将JavaBean样式的类用于其他事情,例如对于IRC bot,每个用户都有一个对象,可以用各种各样的东西进行更新。我不想每次提供新信息时都创建一个新对象,我想将其添加到现有对象中。

    所以我的问题是:使用JavaBeans进行数据存储是一种不好的做法,应该避免,还是完全安全?

    6 回复  |  直到 15 年前
        1
  •  20
  •   OscarRyz    15 年前

    看来你误读了课文。

    现在我可以同意上一个,但在我看来,列表中的JavaBeans比嵌套映射更有意义

    …应该调用构造函数,而不是set*方法,并且对象应该是不可变的

    这是一个很好的实践,在处理线程时特别有用。

    但我们不能说使用setter 巴阿德 或者,特别是当单个线程正在使用对象时。非常安全。

    使用JavaBeans进行数据存储是一种不好的做法,应该避免,还是完全安全?

    不,这是个不错的做法。不是 非常安全 任何一个。视情况而定。

    可变对象(而不是JavaBeans本身)的问题是使用不同的线程来访问它们。

    必须同步访问,以避免一个线程在另一个线程访问对象时修改该对象。

    为了确保对象是不可变的,您必须将属性声明为final。

    class MyBean  {
        private final int i;
    }
    

    如果你想给 MyBean.i 必须在构造函数中指定它:

     public MyBean( int i ) {
         this.i = i;
     }
    

    因为变量是final,所以不能使用setter。你只需要提供一个getter。

    这是完全线程安全的,最好的是,您不必同步访问,因为如果两个线程尝试获取 i 它们都将始终看到实例化时分配的值,您不必同步任何内容。

    如果将来需要处理多线程应用程序,可以考虑使用不可变的JavaBean;)

    顺便说一句,创建不可变bean并仍然提供一堆setter的替代方法是使用 Builders 比如:

     Employee e = new EmployeeBuilder()
                      .setName("Oscar")
                      .setLastName("Reyes")
                      .setAge(0x1F)
                      .setEmployeeId("123forme")
                      .build(); 
    

    它看起来非常类似于常规bean中使用的常规setXyz,其优点是使用不可变数据。

     Employee e = Employee.withName( e, "Mr. Oscar");
    

    它获取现有的对象,复制所有的值,然后设置一个新的值。。。。

     public static EmployeeWithName( Employee e , String newName ){
          return new Employee( newName, e.lastName, e.age, e.employeeId );
      }
    

    但是,在单线程模型中,使用getter/setter是完全安全的。

    PS我强烈建议你买这本书: Effective Java . 你永远不会后悔,你会有信息来判断更好的文章,比如被引用的文章。

        2
  •  6
  •   JUST MY correct OPINION    15 年前

    • 设置第一个属性;
    • 设置第二个属性;
    • 设置最终属性;

    现在你的课可以使用了。那么这里有什么问题?在实例化类和设置最终属性之间,您有一个对象处于内部不一致或不可用的状态,但是没有什么可以阻止您意外地使用它。我更喜欢一个系统,在这个系统中,类在实例化时自动处于一致的、可用的状态。出于这个原因,我更喜欢传递构造函数中的所有初始状态,或者,如果所述初始状态太复杂,则以散列映射或集合等的形式传递初始状态。用例场景现在是:

    • (可选:设置参数对象) ;
    • 使用对象实例。

    当然,这种设置最适合于更简单的对象。对于具有可选属性等更复杂的对象,您需要更进一步,使用其他人向您指出的生成器模式。当您有更复杂的场景时,构建器是不错的,IMO,但是对于更简单、更直接的参数化,仅仅使用构造函数参数或某种类型的参数对象就足够了。

        3
  •  3
  •   stakx - no longer contributing Saravana Kumar    13 年前

    “JavaBeans模式有严重的缺点。”

    我喜欢那些家伙。断章取义已经是我不相信这篇文章的理由。

    编辑: 请参阅Google Books上的effectivejava中的第2项(“当面临许多构造函数参数时考虑一个生成器”): http://books.google.com/books?id=ka2VUBqHiWkC&lpg=PP1&pg=PA11#v=onepage&q&f=false

        4
  •  2
  •   Fortyrunner    15 年前

    新人(“param 1”,“param 2”,“param 3”,“param 4”,“param 5”,“param 6”,“param 7”,“param 8”)

    那你的目标太复杂了。您将需要参数对象(请参阅martinfowler重构手册)。

    当您需要更改对象时,添加一个复制构造函数(即clone方法)。现代的jvm处理这个问题非常容易和迅速,而且几乎没有速度损失。您还可以使Hotspot和GC变得简单。

        5
  •  0
  •   Yann Ramin    15 年前

    java.util.Map . 你获得了类型安全,更容易理解的代码,并避免你的代码最终在每日WTF。注意,实现应该是隔离的——不要在数据存储类中混合太多的逻辑(除了简单的验证)。你应该看看 POJOs

        6
  •  0
  •   mdma    15 年前

    这篇文章的用意是好的,但在实践中,避免使用beans和setters是很难坚持的。例如,让框架使用构造函数在许多情况下是不可能的,因为名称通常是标识特性,并且方法/构造函数参数名称不在.class文件中维护(尽管至少有一个 library

    setter是下一个最好的东西-不是作为“纯”OO,而是相对于构造函数的巨大便利,并且在实践中工作得很好。

    当测试因为“坏的”javabean而开始失败时,我将重新考虑它。但到目前为止我还没见过。唯一一次我认为它们可能不合适的是在多线程代码中使用共享bean,因为同步共享的可变状态很棘手。避开这些,豆子就没事了。

    推荐文章