【问题标题】:Design Patterns with database usage使用数据库的设计模式
【发布时间】:2014-02-04 01:16:57
【问题描述】:

我看到 99% 的设计模式示例(策略、工厂、装饰器等)都带有硬编码信息,每个产品都属于不同的类等。但是,在大多数现实生活中的应用程序中,主要是使用数据库,我们知道为每个产品创建一个类或使用硬编码信息是不切实际的。

我知道它们都是例子,但我认为在你从书上学习之后会很痛苦:

为 CheesePizza、VeggiePizza.. 和商店创建类 纽约商店、芝加哥商店

对于工厂模式.. 在现实生活中,所有这些比萨饼和商店都只是数据库中的行。

那么,在这种情况下,使用数据库和设计模式的最佳方法是什么?

  1. 如果比萨饼和商店在数据库中,则不需要使用设计模式。
  2. 使用设计模式,而不是为每个 Pizza 或 Store 创建一个类,只需创建一个从数据库读取数据的类实现(例如 DatabasePizza 和 DatabaseStore!)。

我了解设计模式对支付业务的重要性,例如。 (现金、信用卡、比特币……)其中每一种支付类型都有独特的专长,并且业务并未完全在数据库中(信用卡需要打印收据,比特币才能访问网络服务等)。

但我要问的是:在一个真正的比萨餐厅,价格、配料、配料,都根据不同的地方(芝加哥,纽约..)位于数据库中,设计模式的使用真的有必要吗?当大量业务位于数据库时,设计模式的使用自然会减少?

【问题讨论】:

  • 您的问题标题通常会引入设计模式,但您实际上只是在询问创建模式。可以使用的设计模式有很多,但在对象持久化领域中可能会少一些。
  • @EricWoodruff 在结构模式(装饰器)和(行为)中我看到了同样的事情。我知道例如付款行为。 (现金、信用卡、比特币等)更改较少,可以硬编码。但是有一些存储在数据库中的行为?那可以在运行时添加吗?我做的事?使用 DB 适应 Strategy Pattern(只有一个 DbBehavior),还是忘记了在这种情况下没用的 Strategy Pattern?
  • 你应该看看type object pattern

标签: database oop design-patterns


【解决方案1】:

...在现实生活中,所有这些比萨饼和商店都只是排成一排 数据库。

数据库是否检查您的类提供的不变量、业务规范或其他一些自定义规则(在 oop 术语中)? 。数据库只是大多数应用程序的存储。

这些行是根据您的域模型和业务逻辑进行智能可靠计算的结果。
设计模式可以帮助您构建可以涵盖所有这些业务规则的灵活代码。

我们知道为每个产品创建一个类是不切实际的

设计模式只是对行为专业化进行了一些抽象,并不关心严格的数据性质
事实上,如果创建了 ChicagoPizza 类,这是为了指定一些独特的专业化,而不是简单地标记:“这个披萨是芝加哥的”。

我不知道有多少应用程序会处理与同一主题相关的数十个对象,它们都有一些强大而独特的专业化

在创建模式的情况下(如您所提到的),我会说如果您有这么多仅因“性质”不同而不同的“对象”,那么您应该只得到一种简单的type 属性(在基类上)映射到数据库中,而不是在这种情况下使用额外的子类。

我完全没有发现编程书籍中提到的内容与软件现实之间存在差距。

您的领域模型(根据定义硬编码)几乎总是比数据库思维更受青睐。

总结:

我知道它们都是例子,但我认为在你从书上学习之后会很痛苦

如果“示例”意味着与现实不同,那么它们根本就不是示例。
它们只是可以制作的真实软件的一小部分。

【讨论】:

    【解决方案2】:

    我认为您对设计模式示例的理解有点过于字面化了。显然,CheesePizza 和 VeggiePizza 示例并不是建议每次您有一个处理比萨饼的软件应用程序时,您都必须使用特定的设计模式。设计模式建议您如何通过打破不必要的依赖关系来设计系统架构以获得更好的可扩展性和可维护性,然后由您决定哪种设计模式最适合您的应用程序。

    工厂模式与数据库没有直接关系,它只是以类似于外观模式的方式指定一个工厂对象,其中不需要实例化对象并且通常/理想情况下使用代码永远不会知道它是什么具体对象使用,因为工厂对象将服务于接口、基类或抽象类。

    无论您选择什么设计模式,您的系统都应该始终与数据库无关,而设计模式将通过打破依赖关系并避免不必要的对象和层耦合来帮助您实现这一目标。因此,基本上您将拥有一个数据访问层,它将您的应用程序从底层数据层抽象出来,并且您的应用程序不需要知道数据库是存储在 MS SQL 数据库、XML 文件、文件系统还是物理上仓库。

    如果比萨饼和商店在数据库中,则不需要使用设计模式。

    这是对设计模式的错误解释。 Pizzas 应该存储在 Pizza 表中,而 Stores 应该存储在 Store 表中。您应该有一个数据访问层来管理这些数据并将它们转换为 POCO 数据实体。您可以手动执行此操作,也可以使用流行的 ORM 工具(例如 NHibernate 或实体框架)

    使用设计模式,而不是为每个 Pizza 或 Store 创建一个类,只需创建一个从数据库读取数据的类实现(例如 DatabasePizza 和 DatabaseStore!)。

    类似的,你应该有 DatabasePizza(你命名它)实现一个接口并从数据库中读取数据并公开一些方法,然后你将有一个 PizzaEntity,它只是一个 POCO 对象,具有诸如 Id、Name 等属性,价格等...然后您的工厂对象将“服务”构造此 DatabasePizza 对象...这是一个简约的示例...

    public static DataFactory
    {
        public static IDatabasePizza DatabasePizza
        {
            get{ return new DatabasePizza;}
        }
    }
    

    然后客户端应用程序、存储库、服务或业务层可以像这样调用这个工厂对象...

    IList<PizzaEntity> favouritePizzas = DataFactory.DatabasePizza.GetMyFavouritePizzas();
    

    希望您了解设计模式背后的想法。我建议您阅读GoF's book on Design Patterns,它是一个很好的信息来源,它附带了一些项目,您可以在其中浏览源代码

    【讨论】:

    • 我认为使用具有规则和独特专长且与数据库不完全相关的支付(现金、信用卡、比特币等)的创建或行为模式是公平的。 GOF 的书籍示例也是如此。但是在与数据库密切相关的情况下(比萨店示例),从数据库中读取比萨饼似乎不是太多的工厂模式?这就是为什么我想知道,如果在这种情况下最好不要使用工厂模式,例如。
    • 这听起来像是业务逻辑,实际上与数据库访问无关。您的业​​务逻辑应该与您的数据访问层分离,并且彼此之间应该具有零依赖关系。在您的情况下,对于这种支付方式对象,我更喜欢使用 DI 和 IoC 模式的组合,我可以根据给定条件在“业务对象”之间切换......但是,同样,每个项目都是独一无二的,我我不是建议特定设计模式的人,因为我不知道您的项目是如何设计的
    【解决方案3】:

    任何关于设计模式的例子都只是一个简单的例子或插图。他们通常使用硬编码值来保持范围小(而不是查询数据库)。例如,使用的许多案例似乎不正确或不太适合现实生活的需要。

    以您的CheesePizzaVeggiePizza 为例。两者都是数据库中Pizza 表上的两条主记录。这是正确的,目前不需要设计模式,只需要一个Pizza 类实体。

    现在随着业务的增长,您将需要另一种Pizza,而不是原来的Pizza。假设新类是PizzaWithAdditionalTopping。从现在开始,装饰器或策略或工厂设计模式将开始大放异彩,因为新类——IAdditionalToppingAble (PizzaWithAdditionalTopping) 现在将具有额外的属性IEnumerable&lt;Topping&gt; Toppings,其中需要专门处理并与@ 不同987654330@。

    假设业务再次增长,现在您有一个IStuffedCrustAble (StuffedCrustedPizza) 比萨饼。现在StuffedCrustedPizza 类将拥有另一个属性string StuffedCrustType(或使用枚举)。再次使用这些设计模式,希望他们可以在不修改现有代码的情况下添加行为。

    您也可以进行其他设计,即使将Toppings 添加到您原来的Pizza 类,或使用if-else、DataTable 或任何没有设计模式的东西,但根据经验,可维护性会降低.

    【讨论】:

      【解决方案4】:

      如果比萨饼和商店在数据库中,则不需要使用设计 模式。

      您对设计模式的使用不应受到您存储/持久化数据的方式的影响。设计模式可帮助您使用已知和完善的解决方案解决常见问题。您存储数据的位置/方式与您使用的模式无关。

      使用设计模式,而是为每个 Pizza 或 Store 创建一个类, 只需创建一个从数据库读取数据的类实现 (例如,DatabasePizza 和 DatabaseStore!)

      设计您的模型以解决您的业务问题。不要设计存储模型。那不是OO。让 ORM 或您自己的持久性技术来处理将数据从磁盘上移入和移出的繁琐事务。

      如果一个 NyPizza 装饰一个由成分组合而成的比萨饼是解决业务问题的正确模型,那么就这样做。不要让持久性影响你的模型。有时必须做出一些权衡:某些 ORM 有某些怪癖。但是,模型及其使用的任何设计模式都应该是独立的,并且与持久性无关。

      【讨论】:

        【解决方案5】:

        我没有研究过模式,但我正在这样做:我处理不同的机器,所以我用通用代码(id、标签、机器之间的链接)实现了一个类,然后还有一个映射;在 db 中创建了一个称为子类的表,添加了基本行和映射(使用键作为列名。显然映射键几乎不应该在子类中更改,因为它必须使用更改表来处理,并且会很危险。这样我就有一个适用于每种机器的表。数据以这种方式加载;你给出类的名称,witch 也是表名,地图被加载到一个列表中,那么谁需要info 在特定类的构造函数中传递地图。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-18
          • 2021-11-08
          相关资源
          最近更新 更多