设计模式逐步“填写”对象(初学者问题)

时间:2011-04-28 01:46:12

标签: java design-patterns

我需要处理一堆数据 - 每个元素(数据?)基本上只是一个文本属性的字典。所以说课程是Book - 它可能有作者,标题,流派,阅读难度等级和推荐价格。现在,我开始只知道前两个,并且对于每本书,需要推断或估计接下来的三个(在我的问题中它不仅仅是那个)。
因此,对我来说很自然的方法是对每本书进行迭代迭代。我的设计看起来像是(这是Java)

public class Book
{
    public String author;
    public String title;
    /* ... */
    public double price;
    public Book(String author,String title)
    {
        this.author = author;
        this.title = title;
    }

    public void setGenre(DataProvider dp,...)
    {
        /* some sort of guess, resulting in genreGuess */
        this.genre = genreGuess;
    }

    /* .. and so on for price, etc */
}

然后,我的代码想:

for (Book book : bookList)
{ 
    setGenre(book);
    setPrice(book);
    /* and so on */
}

然而,我正在尝试学习如何以较少的迭代方式更好地设计程序,使用较少的可变状态。有没有人对我如何做到这一点有任何建议?

3 个答案:

答案 0 :(得分:1)

这里的关键是你所描述的课程非常简单,所以很难看出它是如何改进的。

然而,在实际系统中会发生什么,例如,您的作者类将是与人员和合同的连接,或者本书将具有发布者。在图书馆中,它可能有购买时间,借出和退回时的历史记录,以及ISBN和国会图书馆记录等内容。

对象的背后是某种持久存储 - 从Python的“酸洗”到关系数据库或“NoSQL”表存储这样简单的东西。

这就是复杂性开始出现的地方。

所以这里有一些事情要考虑:

  • 您要存储多少个对象? 10本书的决定与你需要存储1000万册的决定非常不同。

  • 如果你有一个复杂的对象树 - 包括发布者,作者,人,合同,LC记录,库存等等 - 那么从.persistent store创建(或“再水化”)对象就可以了很长时间。当OO第一次出现时,这是forst系统中的一个传统问题:对象模型非常棒,但加载一个对象及其所有连接对象需要花费半小时。

    此时,您需要开始考虑lazy evaluation。另一个有用的模式是Flyweight - 您可以缓存一个副本并简单地引用它,而不是制作许多副本。

  • 用例是什么?你不能只是说“我想要一本书的模型”,因为你不知道这本书的内容是 。从用例开始,逐步实现让类的方法更容易编写代码的目标。

    处理它的最佳方法基本上是编写代码。使用您的对象写出,草图,实际的代码示例,看看它们是否易于使用。

  • 正如弗雷德布鲁克斯所说,“计划扔掉一个;无论如何你都会。”在编写散文时,编写代码就是重写。

答案 1 :(得分:1)

我不是OO设计大师...这是我个人认为更好的一种方式。

将GenreGuesser接口的实现注入Book ...这最好通过BookFactory完成。工厂配置为ONCE,然后用于创建“喜欢”的书籍。我想在这里使用依赖注入(比如Springs DI框架,或Google的Guice),这大大减少了将工厂“连接”到依赖于它们的东西的开销; - )

然后我们可以即时检索AND CACHE计算的属性。请注意,缓存结果意味着Book-objects IDENTITY(例如:author& title)是最终的,或至少固定一次。

public String getGenre()
{
  if (this.genre==null) 
    this.genre = genreGuesser.getGuess();
  return this.genre;
}

所以基本上你为每个计算字段做了自己的“后期绑定”。如果默认的“猜测”偏离基础,也没有什么能阻止你(或用户)手动设置每个字段。

这在Book类上提供了一个简单的“丰富”界面;以使Book意识到“猜测”这个概念为代价......而且我不是“智能”转移对象的粉丝本身,这让人想起另一种方法。

如果我们要接受拥有BookFactory课程的所有开销,并且我们只限于通过工厂创建书籍,那么为什么不让BookFactory(根据定义知道所有关于Book和它的属性)用(猜测的)默认值填充所有计算字段。然后Book类又回到了一个简单,愚蠢的转移对象,它完全符合它所需要的,而且没有它。

我有兴趣阅读其他建议。

干杯。基思。

答案 2 :(得分:0)

我注意到的第一件事是setGenre和setPrice是Book对象的成员方法。在这种情况下,你不应该传书,而应该是

book.setGenre();
book.setPrice();

但我不确定你是否应该这样做。如果你试图从作者和标题中推断出Genre和Difficulty以及最终的Price,你就不应该明确地调用setGenre()。

相反,你可以打电话给

book.getPrice();

book.calculatePrice();

然后,该方法可以在返回最终价格之前推断性别和难度。

相关问题