Java 面向对象设计-我的值对象应该只包含getter吗?

Java 面向对象设计-我的值对象应该只包含getter吗?,java,oop,Java,Oop,在我项目的业务逻辑中,我主要有“价值对象”和“管理者” 价值对象到处都是。它们可以是用户、汽车、照片、相册等等 管理者的存在是为了控制他们的价值对象。它可以是UserManager、CarManager、PhotoManager、AlbumManager等等。它们使用值对象创建/删除/获取列表和其他操作 现在我面临一个问题:我的值对象是否应该包含设置器? 我的第一个意见是否定的,因为我认为只有他的经理才能控制价值对象状态 但是有一个坏的方面——代码重复和明显的重复工作 如果没有setters,我

在我项目的业务逻辑中,我主要有“价值对象”和“管理者”

价值对象到处都是。它们可以是用户、汽车、照片、相册等等

管理者的存在是为了控制他们的价值对象。它可以是UserManager、CarManager、PhotoManager、AlbumManager等等。它们使用值对象创建/删除/获取列表和其他操作

现在我面临一个问题:我的值对象是否应该包含设置器? 我的第一个意见是否定的,因为我认为只有他的经理才能控制价值对象状态

但是有一个坏的方面——代码重复和明显的重复工作

如果没有setters,我的管理器将具有类似于
userManager.addPhoto(userToAddTo,photobedded)
的方法,该方法在内部调用
user.addPhoto(photo)
(方法
addPhoto
存在于实现中,但不在接口中)。如果只有两种这样的方法是可以的,但是当它得到很多这样的“setter”方法时,经理似乎有点难看,这显然是双重工作


那么,我是否应该在我的值对象中使用setter呢?

您的值对象是数据访问层的一部分,而管理器是业务逻辑的一部分。因此,setter和getter显然是数据访问层的一部分,而不是业务逻辑的一部分。当您不确定应该在哪一层执行特定操作时,还必须考虑实体或业务逻辑的可重用性

但是要小心。您的实体只应具有如下设置器:

    /**
     * @param Name
     */
    public void setName(sName) {
        m_sName = sName;
    }
如果您想用一些值做一些特定的事情,这是业务逻辑的一部分,因为它具有可重用性

我会说“是”,我也会避免像userManager.addPhoto(userToAddTo,photobedded)这样的东西,转而使用更丰富的域模型,比如user.addPhoto(photo)

我认为大多数OOD设计社区都倾向于“为属性添加setter和getter”。当然,有些纯粹主义者认为您应该一次只管理完整状态,但这并不实际

如果你看看像C#或Groovy这样的语言,它们已经使getter和setter的思想有些过时,依靠各种机制来简单地处理直接可分配/可读的属性,并允许一些“隐藏”的方法添加get/set逻辑:

class Person {
  String name
  String lastname

  // for some dumb reason, always 'get' upper-cased last names
  String getLastname() {
    return this.lastname.toUpperCase()
  }
}
总而言之,我支持OO设计,其中对象表示状态业务逻辑,而不是像数据库表中的一行那样对简单状态的无力反映


我也会考虑问自己为什么要使用简单/哑值对象。是否需要它们,比如跨越电线上的系统边界?

事先我会说,我不明白为什么必须将设计划分为值对象和管理器对象,您最好有一个非常好的理由这样做。在我的例子中,我总是用自己的GETER和SETER方法实现数据传输对象,如果我认为必须从API用户自卫;我试着按照乔希·布洛赫在书中建议的防守方法

这意味着,如果我不希望API用户修改我返回的DTO,我将使用
final
修饰符使这些对象不可变,如果需要,还将返回其属性的防御性副本。。。任何必要的。与Java处理字符串或整数的方式相同


当然,如果您的经理除了编写属性之外还做了其他事情,那么他们就是业务逻辑的一部分,您所做的一切都是完全合理的

不,您的属性必须有一个setter来设置它。当属性由其他属性组成时,将使用无setter属性

使用扩展和工厂模式存储等有什么问题?因此,您将拥有一个通用的管理器类,然后根据需要对其进行扩展。主要原因是可重用性!您的代码是否是某个人的API?有人会在你的基础上构建代码吗?在这种情况下,我建议你考虑不可改变的方法,或者今天我特别密集地看到设计的原因,所以请不要把我自己看得太重:P2值对象和管理者都是域逻辑的一部分。对数据访问层的访问是通过管理器实现的,因此除了他们之外,没有人知道数据访问层。值对象是实体。如果要将这些实体存储在数据库中,它们怎么可能是数据访问层的一部分呢?值对象只是域逻辑中使用的接口。它们可以存储在任何地方——文件系统、数据库等等。它们的存储位置—取决于实现是的,您是对的。它们是为某种类型的数据库或其他持久性机制提供抽象接口的对象。因此,它们肯定是数据访问层的一部分。如果在控制器中调用
userManager.get()
(我的用户是由管理员从数据库中获取的),然后在同一控制器中调用
User.addPhoto(photo)
userManager.save(User)
,那么用户是数据访问层的一部分吗?