vlambda博客
学习文章列表

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

第 2 章 GOF 设计模式概述 - 核心设计模式

在本章中,您将获得 GOF 设计模式的概述,包括一些用于进行应用程序设计的最佳实践。您还将获得对常见问题的概述——使用设计模式解决问题。

我将解释 Spring Framework 常用的设计模式,以实现更好的设计和架构。我们都在一个全球化的世界中,这意味着如果我们在市场上有服务,就可以在全球范围内访问它们。简单地说,现在是分布式计算系统的时代。那么首先,什么是分布式系统?它是一个应用程序,它被分成较小的部分,在不同的计算机上同时运行,较小的部分通过网络进行通信,通常使用协议。这些较小的部分称为 tiers。因此,如果我们想创建一个分布式应用程序,n-tier 架构是该类型应用程序的更好选择。但是开发 n 层的分布式应用程序是一项复杂且具有挑战性的工作。将处理分配到单独的层可以提高资源利用率。它还支持将任务分配给最适合工作和开发特定层的专家。开发分布式应用程序存在许多挑战,这里详细介绍了其中的一些挑战:

  • Integration between the tiers
  • Transaction management
  • Concurrency handling of enterprise data
  • Security of the application and so on

因此,我在本书中的重点是通过使用 Spring Framework 应用模式和最佳实践来简化 Java EE 应用程序的设计和开发。在本书中,我将介绍一些常见的 GOF 设计模式,以及 Spring 如何采用这些模式为上述列出的企业应用程序问题提供最佳解决方案,因为分布式对象的设计是一项极其复杂的任务,即使对于经验丰富的专业人士也是如此。在起草最终解决方案之前,您需要考虑关键问题,例如可扩展性、性能、事务等。该解决方案被描述为一种模式。

在本章结束时,您将了解设计模式如何为解决任何与设计相关和开发相关的问题提供最佳解决方案,以及如何使用最佳实践开始开发。在这里,您将获得有关 GOF 设计模式的更多想法,并附有真实示例。您将获得有关 Spring Framework 如何在内部实现这些设计模式以提供最佳企业解决方案的信息。

本章将涵盖以下几点:

  • Introducing the power of design patterns
  • Common GOF Design Patterns overview
    • Core design patterns
      • Creational design patterns
      • Structural design patterns
      • Behavioral design patterns
    • J2EE design patterns
      • Design patterns at presentation layer
      • Design patterns at business layer
      • Design patterns at integration layer
  • Some best practices for Spring application development

介绍设计模式的力量


那么什么是设计模式呢?实际上,短语设计模式与任何编程语言都没有关联,也没有针对问题提供特定语言的解决方案。设计模式与重复问题的解决方案相关联。例如,如果任何问题经常发生,则该问题的解决方案已被有效地使用。任何不可重用的问题解决方案都不能被视为模式,但问题必须经常发生才能有可重用的解决方案,并被视为模式。因此,设计模式是一种软件工程概念,用于描述软件设计中常见问题的重复解决方案。设计模式也代表了经验丰富的面向对象软件开发人员使用的最佳实践。

当您为应用程序进行设计时,您应该考虑所有常见问题的解决方案,这些解决方案称为设计模式。整个开发团队必须对设计模式有很好的理解,这样员工才能有效地相互沟通。事实上,你可能熟悉一些设计模式;但是,您可能没有使用众所周知的名称来描述它们。本书将带您一步一步地学习,并在您学习设计模式概念的同时向您展示使用 Java 的示例。

design 模式具有三个主要特征:

  • A Design pattern is specific to a particular scenario rather than a specific platform. So its context is the surrounding condition under which the problem exists. The context must be documented within the pattern.
  • Design patterns have been evolved to provide the best solutions to certain problems faced during software development. So this should be limited by the context in which it is being considered.
  • Design patterns are the remedy for the problems under consideration.

例如,如果开发人员指的是 GOF 单例设计模式并表示使用单个对象,那么所有相关的开发人员都应该明白,您需要设计一个在应用程序中只有一个实例的对象。所以 Singleton 设计模式将由单个对象组成,开发人员可以互相告诉对方程序遵循 Singleton 模式。

通用 GoF 设计模式概述


作者 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 通常被称为 GoF 或四人帮。他们出版了一本名为Design Patterns: Elements of Reusable Object-Oriented Software的书,开创了软件开发中设计模式的概念。

在本章中,您将了解 GOF 模式是什么以及它们如何帮助解决面向对象设计中遇到的常见问题。

Gang of Four (GoF) 模式是 23 个经典软件design 模式为软件设计中的常见问题提供反复出现的解决方案。这些模式在Design Patterns: Elements of Reusable Object-Oriented Software一书中定义。这些模式分为两大类:

  • Core Design Patterns
  • J2EE Design Patterns

此外,核心设计模式还细分为三大类design模式,如下:

  • Creational Design Pattern: Patterns under this category provide a way to construct objects when constructors will not serve your purpose. The creation logic of objects is hidden. The programs based on these patterns are more flexible in deciding object creation according to your demands and your use cases for the application.
  • Structural Design Pattern: Patterns under this category deal with the composition of classes or objects. In the enterprise application, there are two commonly used techniques for reusing functionality in object-oriented systems: one is class Inheritance and the other is the Object Composition Concept of inheritance. The Object Composition Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities.
  • Behavioral Design Pattern: Patterns under this category, characterize the ways in which classes or objects interact and distribute responsibility. These design patterns are specifically concerned with communication between objects. The behavioral design pattern is used to control and reduce complicated application flow in the enterprise application.

现在,让我们看看 other 类别,即 JEE 设计模式。这是设计模式的另一个主要类别。通过应用 Java EE 设计模式可以极大地简化应用程序设计。 Java EE 设计模式已记录在 Sun 的 Java 蓝图中。这些 Java EE 设计模式为 Java EE 应用程序的不同层中的对象交互提供了久经考验的解决方案指南和最佳实践。这些设计模式特别关注以下列出的层:

  • Design pattern at the presentation layer
  • Design pattern at the business layer
  • Design pattern at the integration layer

让我们在接下来的部分探索创造设计模式。

创造型设计模式


让我们看看这个类别的底层设计模式,以及 Spring Framework 如何采用它们来提供组件之间的松散耦合和 create 并管理 Spring 组件的生命周期。创建型设计模式与对象创建方法相关联。对象的创建逻辑对这个对象的调用者是隐藏的。

我们都知道如何在 Java 中使用 new 关键字来创建对象,如下:

     Account account = new Account(); 

但是这种方式并不适合某些情况,因为它是一种硬编码的方式来创建一个对象。创建对象也不是最佳实践,因为对象可能会根据程序的性质而更改。在这里,创建设计模式提供了根据程序性质创建对象的灵活性。

现在让我们看看这个类别下的不同设计模式。

工厂设计模式

定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法让类将实例化推迟到子类。 - GOF 设计模式

工厂设计模式是一种创造型设计模式。工厂设计模式也称为工厂方法设计模式。根据这种设计模式,您无需将底层逻辑暴露给客户端即可获得一个类的对象。它通过使用公共接口或抽象类将新对象分配给调用者。这意味着设计模式隐藏了对象实现的实际逻辑,如何创建它,以及在哪个类中实例化它。因此客户端不必担心创建、管理和销毁一个对象——工厂模式负责这些任务。工厂模式是 Java 中最常用的设计模式之一。

让我们看看工厂模式的好处:

  • The Factory pattern promotes loose coupling between collaborating components or classes by using interfaces rather than binding application-specific classes into the application code
  • Using this pattern, you can get an implementation of an object of classes that implement an interface, at runtime
  • The object life cycle is managed by the factory implemented by this pattern

现在让我们讨论一些应该应用工厂设计模式的常见问题:

  • This pattern removes the burden on the developer to create and manage the objects
  • This pattern removes the tight coupling between collaboration components because a component doesn't know what subclasses it will be required to create
  • Avoid hard code to create an object of the class

在 Spring Framework 中实现工厂设计模式

Spring Framework 透明地使用这种 Factory 设计模式来使用 BeanFactoryApplicationContext 接口来实现 Spring 容器。 Spring 的容器基于工厂模式为 Spring 应用程序创建 Spring bean 并管理每个 Spring bean 的生命周期。 BeanFactoryApplicationContext 是工厂接口,Spring 有很多实现类。 getBean() 方法是相应地为您提供 Spring bean 的工厂方法。

让我们看一个工厂设计模式的示例实现。

工厂设计模式的示例实现

有两个类 SavingAccountCurrentAccount 实现了一个接口 Account。因此,您可以创建一个 Factory 类,其方法采用一个或多个参数,其返回类型为 Account。此方法称为工厂方法,因为它创建 CurrentAccountSavingAccount 的实例。 Account 接口用于松耦合。因此,根据工厂方法中传递的参数,它选择实例化哪个子类。这个 factory 方法将超类作为它的返回类型:

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

工厂设计模式的 UML 图

让我们在下面的示例中看一下这种设计模式。在这里,我将创建一个 Account 接口和一些实现 Account 接口的具体类:

    package com.packt.patterninspring.chapter2.factory;
    public interface Account { 
      void accountType(); 
   } 

现在让我们创建 SavingAccount.java,它将实现 Account 接口:

    package com.packt.patterninspring.chapter2.factory; 
    public class SavingAccount implements Account{ 
      @Override 
      public void accountType() { 
         System.out.println("SAVING ACCOUNT"); 
      } 
    } 

CurrentAccount.java 相同,它也会实现 Account 接口:

    package com.packt.patterninspring.chapter2.factory; 
    public class CurrentAccount implements Account { 
      @Override 
      public void accountType() { 
         System.out.println("CURRENT ACCOUNT"); 
      } 
    } 

现在将定义一个工厂类 AccountFactoryAccountFactory 生成具体类的对象,SavingAccountCurrentAccount,基于作为 Factory 方法的参数给出的帐户类型:

AccountFactory.java 是一个工厂来产生 Account 类型的对象:

    package com.packt.patterninspring.chapter2.factory.pattern; 
    import com.packt.patterninspring.chapter2.factory.Account; 
    import com.packt.patterninspring.chapter2.factory.CurrentAccount; 
    import com.packt.patterninspring.chapter2.factory.SavingAccount; 
    public class AccountFactory { 
      final String CURRENT_ACCOUNT = "CURRENT"; 
      final String SAVING_ACCOUNT  = "SAVING"; 
      //use getAccount method to get object of type Account    
      //It is factory method for object of type Account 
      public Account getAccount(String accountType){   
         if(CURRENT_ACCOUNT.equals(accountType)) {   
               return new CurrentAccount();   
         }
         else if(SAVING_ACCOUNT.equals(accountType)){   
               return new SavingAccount();   
         }    
         return null;   
      }   
    } 

FactoryPatternMainAccountFactory 获取 Account 对象的主要调用类。它将一个参数传递给包含帐户类型信息的工厂方法,例如 SAVINGCURRENTAccountFactory 返回您传递给工厂方法的类型的对象。

让我们创建一个演示类 FactoryPatterMain.java 来测试工厂方法设计模式:

    package com.packt.patterninspring.chapter2.factory.pattern; 
    import com.packt.patterninspring.chapter2.factory.Account; 
    public class FactoryPatterMain { 
      public static void main(String[] args) { 
         AccountFactory accountFactory = new AccountFactory(); 
         //get an object of SavingAccount and call its accountType()
         method. 
         Account savingAccount = accountFactory.getAccount("SAVING"); 
         //call accountType method of SavingAccount 
         savingAccount.accountType(); 
         //get an object of CurrentAccount and call its accountType() 
         method. 
         Account currentAccount = accountFactory.getAccount("CURRENT"); 
         //call accountType method of CurrentAccount 
         currentAccount.accountType(); 
      } 
    } 

您可以测试此文件并在控制台上查看输出,应如下所示:

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

现在我们已经看到了工厂设计模式,让我们转向它的另一个变体——抽象工厂设计模式。

抽象工厂设计模式

提供一个接口,用于创建相关或依赖对象的系列,而无需指定它们的具体类。 - GOF 设计模式

抽象 Factory 模式属于创建设计模式。与工厂方法设计模式相比,它是一种高级设计模式。根据这种设计模式,您只需定义一个接口或抽象类来创建相关的依赖对象,而无需指定其具体子类。所以在这里,抽象工厂返回一个类工厂。让我为你简化一下。你有一套工厂方法设计模式,你只是把这些工厂放在一个使用工厂设计模式的工厂下,这意味着它只是一个工厂的工厂。而且不需要把所有工厂的知识都带进工厂——你可以用顶级工厂来做你的程序。

在抽象工厂模式中,接口负责创建相关对象的工厂,而无需明确指定它们的类。每个生成的工厂都可以按照 Factory 模式提供对象。

抽象工厂模式的好处如下:

  • The Abstract Factory Design provides loose coupling between the component families. It also isolates the client code from concrete classes.
  • This design pattern is a higher-level design than the Factory pattern.
  • This pattern provides better consistency at construction time of objects across the application.
  • This pattern easily swaps component families.

应该应用抽象工厂设计模式的常见问题

当您为应用程序中的对象创建设计 Factory 模式时,有时您希望使用某些约束创建一组特定的相关对象,并在应用程序中的相关对象之间应用所需的逻辑.您可以通过在工厂内为一组相关对象创建另一个工厂并应用所需的约束来实现此设计。您还可以将逻辑编程到一组相关对象。

当您想自定义相关对象的实例化逻辑时,您可以使用这种设计模式。

在 Spring Framework 中实现抽象工厂设计模式

在 Spring Framework 中,FactoryBean 接口基于抽象 Factory 设计模式。 Spring提供了很多这个接口的实现,如ProxyFactoryBeanJndiFactoryBeanLocalSessionFactoryBean< /code>、LocalContainerEntityManagerFactoryBean 等。 FactoryBean 也有助于 Spring 构造它自己无法轻易构造的对象。这通常用于构造具有许多依赖项的复杂对象。当构造逻辑本身高度易变并且依赖于配置时,也可以使用它。

例如,在 Spring Framework 中,FactoryBean 实现之一是 LocalSessionFactoryBean,它用于获取一个 bean 的引用与休眠配置相关联。它是关于数据源的特定配置。它应该在您获得 SessionFactory 的对象之前应用。您可以使用 LocalSessionFactoryBean 以一致的方式应用特定的数据源配置。您可以将 FactoryBean 的 getObject() 方法的结果注入到任何其他属性中。

让我们创建一个抽象工厂设计模式的示例实现。

抽象工厂设计模式的示例实现

我将创建一个 BankAccount 接口以及一些实现这些接口的具体类。在这里,我还创建了一个抽象的 factory 类,AbstractFactory。我有一些工厂类,BankFactoryAccountFactory; 这些类扩展了 AbstractFactory 类。我还将创建一个 FactoryProducer 类来创建工厂。

让我们在下图中查看此设计模式:

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

抽象工厂设计模式的 UML 图

创建一个演示类,AbstractFactoryPatternMain;它使用 FactoryProducer 来获取 AbstractFactory 对象。这里我将ICICIYES等信息传递给AbstractFactory来获取Bank的一个对象,我也传递了SAVINGCURRENT 到 AbstractFactory 以获取 Account 类型。

下面是 Bank.java 的代码,它是一个接口:

    package com.packt.patterninspring.chapter2.model; 
    public interface Bank { 
      void bankName(); 
    } 

现在让我们创建 ICICIBank.java,它实现了 Bank 接口:

    package com.packt.patterninspring.chapter2.model; 
    public class ICICIBank implements Bank { 
      @Override 
      public void bankName() { 
        System.out.println("ICICI Bank Ltd."); 
      } 
    } 

让我们创建另一个 YesBank.java,实现 Bank 接口:

    package com.packt.patterninspring.chapter2.model; 
    public class YesBank implements Bank{ 
      @Override 
      public void bankName() { 
         System.out.println("Yes Bank Pvt. Ltd."); 
      } 
   } 

在这个例子中,我使用了与本书中工厂模式示例中使用的相同的接口和实现Account的类。

AbstractFactory.java 是一个抽象类,用于获取 BankAccount< 的工厂/代码>对象:

    package com.packt.patterninspring.chapter2.abstractfactory.pattern; 
    import com.packt.patterninspring.chapter2.model.Account; 
    import com.packt.patterninspring.chapter2.model.Bank; 
    public abstract class AbstractFactory { 
      abstract Bank getBank(String bankName); 
      abstract Account getAccount(String accountType); 
    } 

BankFactory.java 是一个工厂类,扩展了 AbstractFactory 以根据给定的信息生成具体类的对象:

    package com.packt.patterninspring.chapter2.abstractfactory.pattern; 
    import com.packt.patterninspring.chapter2.model.Account; 
    import com.packt.patterninspring.chapter2.model.Bank; 
    import com.packt.patterninspring.chapter2.model.ICICIBank; 
    import com.packt.patterninspring.chapter2.model.YesBank; 
    public class BankFactory extends AbstractFactory { 
      final String ICICI_BANK = "ICICI"; 
      final String YES_BANK   = "YES"; 
      //use getBank method to get object of name bank    
      //It is factory method for object of name bank 
      @Override 
      Bank getBank(String bankName) { 
         if(ICICI_BANK.equalsIgnoreCase(bankName)){   
               return new ICICIBank();   
         } 
         else if(YES_BANK.equalsIgnoreCase(bankName)){   
               return new YesBank();   
         }   
         return null; 
      } 
      @Override 
      Account getAccount(String accountType) { 
         return null; 
      } 
    } 

AccountFactory.java 是一个工厂类,它扩展了 AbstractFactory.java 以根据给定的信息生成具体类的对象:

     package com.packt.patterninspring.chapter2.abstractfactory.pattern; 
     import com.packt.patterninspring.chapter2.model.Account; 
     import com.packt.patterninspring.chapter2.model.Bank; 
     import com.packt.patterninspring.chapter2.model.CurrentAccount; 
     import com.packt.patterninspring.chapter2.model.SavingAccount; 
     public class AccountFactory extends AbstractFactory { 
       final String CURRENT_ACCOUNT = "CURRENT"; 
       final String SAVING_ACCOUNT  = "SAVING"; 
       @Override 
       Bank getBank(String bankName) { 
          return null; 
      } 
      //use getAccount method to get object of type Account    
      //It is factory method for object of type Account 
      @Override 
      public Account getAccount(String accountType){   
        if(CURRENT_ACCOUNT.equals(accountType)) {   
               return new CurrentAccount();   
        }
        else if(SAVING_ACCOUNT.equals(accountType)){   
               return new SavingAccount();   
        }    
        return null;   
      } 
    } 

FactoryProducer.java是一个创建Factory生成器类的类,通过传递一条信息来获取工厂,例如Bank帐号

    package com.packt.patterninspring.chapter2.abstractfactory.pattern; 
    public class FactoryProducer { 
      final static String BANK    = "BANK"; 
      final static String ACCOUNT = "ACCOUNT"; 
      public static AbstractFactory getFactory(String factory){ 
         if(BANK.equalsIgnoreCase(factory)){ 
               return new BankFactory(); 
         }
         else if(ACCOUNT.equalsIgnoreCase(factory)){ 
               return new AccountFactory(); 
         } 
         return null; 
       } 
    } 

FactoryPatterMain.java 是抽象工厂设计模式的演示类。 FactoryProducer 是一个获取 AbstractFactory 的类,以便通过传递一条信息来获取具体类的工厂,例如类型:

    package com.packt.patterninspring.chapter2.factory.pattern; 
    import com.packt.patterninspring.chapter2.model.Account; 
    public class FactoryPatterMain { 
      public static void main(String[] args) { 
         AccountFactory accountFactory = new AccountFactory(); 
         //get an object of SavingAccount and call its accountType() 
         method. 
         Account savingAccount = accountFactory.getAccount("SAVING"); 
         //call accountType method of SavingAccount 
         savingAccount.accountType(); 
         //get an object of CurrentAccount and call its accountType() 
         method. 
         Account currentAccount = accountFactory.getAccount("CURRENT"); 
         //call accountType method of CurrentAccount 
         currentAccount.accountType(); 
      } 
    } 

您可以测试此文件并在控制台上查看输出:

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

现在我们已经看到了抽象的工厂设计模式,让我们转向它的不同变体——单例设计模式。

单例设计模式

确保一个类只有一个实例并提供一个全局访问点 - GOF 设计模式

Singleton 模式是一种创建型设计模式,它是Java 中最简单的设计模式之一。根据单例设计模式,类为每次调用提供相同的单个对象——也就是说,它将类的实例化限制为一个对象,并提供对该类的全局访问点。因此,该类负责创建一个对象,并确保为该对象的每个客户端调用只创建一个对象。此类不允许直接实例化此类的对象。它允许您仅通过公开的静态方法获取对象实例。

需要恰好一个对象来协调系统的动作时,这很有用。您可以使用两种形式创建一个模式,如下所示:

  • Early instantiation: Creation of instance at load time
  • Lazy instantiation: Creation of instance when required

单例模式的好处:

  • It provides controller access to crucial (usually heavy object) classes, such as the connection class for DB and the SessionFactory class in hibernate
  • It saves heaps of memory
  • It is a very efficient design for multithreaded environments
  • It is more flexible because the class controls the instantiation process, and the class has the flexibility to change the instantiation process
  • It has low latency

应该应用单例模式的常见问题

单例模式只解决了一个问题——如果你有一个只能有一个实例的resource,并且你需要管理那个单例,那么你就需要一个单例。通常,如果您想在分布式和多线程环境中使用给定配置创建数据库连接,如果您不遵循单例设计,则可能每个线程都可以使用不同的配置对象创建新的数据库连接.使用单例模式,每个线程在整个系统中获取相同的数据库连接对象和相同的配置对象。它主要用于多线程和数据库应用程序。它用于日志记录、缓存、线程池、配置设置等。

Spring Framework 中的单例设计模式实现

Spring 框架提供单例范围的 bean 作为单例模式。它类似于单例模式,但与 Java 中的单例模式并不完全相同。根据 Singleton 模式,Spring 框架中的作用域 bean 意味着每个容器和每个 bean 一个 bean 实例。如果您在单个 Spring 容器中为特定类定义一个 bean,则 Spring 容器会创建一个且仅一个由该 bean 定义定义的类的实例。

让我们创建一个单例设计模式的示例应用程序。

单例设计模式的示例实现

在下面的代码示例中,我将创建 一个类,如果该类的实例不存在,我将使用该方法创建该类的实例。如果实例已经存在,那么它将简单地返回该对象的引用。我还考虑了线程安全,因此在创建该类的对象之前在这里使用了同步块。

让我们看看 Singleton 设计模式的 UML 图:

    package com.packt.patterninspring.chapter2.singleton.pattern; 
    public class SingletonClass { 
      private static SingletonClass instance = null; 
      private SingletonClass() { 
      } 
      public static SingletonClass getInstance() { 
        if (instance == null) { 
          synchronized(SingletonClass.class){   
               if (instance == null) { 
                  instance = new SingletonClass(); 
               } 
          } 
        } 
       return instance; 
      } 
    } 
  } 

在前面的代码中需要注意的一点是,我编写了 SingletonClass 类的私有构造函数,以确保无法创建该类的对象。这个例子是基于惰性初始化的,也就是说程序第一次按需创建实例。因此,您还可以急切地实例化对象以提高应用程序的运行时性能。让我们看一下带有急切初始化的相同 SingletonClass

    package com.packt.patterninspring.chapter2.singleton.pattern; 
    public class SingletonClass { 
      private static final SingletonClass INSTANCE = 
         new SingletonClass(); 
      private SingletonClass() {} 
      public static SingletonClass getInstance() { 
        return INSTANCE; 
      } 
    } 

现在我们已经看到了单例设计模式,让我们转向它的不同变体——原型设计模式。

原型设计模式

使用原型实例指定要创建的对象类型,并通过复制此原型创建新对象。 - GOF 设计模式

Prototype 模式属于软件开发中 GOF 模式的 creational 设计模式系列。此模式用于通过使用对象的克隆方法来创建对象。它由原型实例确定。在企业应用程序中,对象创建在创建和初始化对象的初始属性方面成本很高。如果您已经掌握了这种类型的对象,那么您就选择原型模式;您只需复制现有的类似对象而不是创建它,这很耗时。

该模式涉及实现原型接口,它创建当前对象的克隆。当直接创建对象的成本很高时使用此模式。例如,假设要在执行昂贵的数据库操作后创建对象。我们可以缓存对象,在下一次请求时返回其克隆,并在需要时更新数据库,从而减少数据库调用。

原型设计模式的好处

以下列表显示了使用原型模式的好处

  • Reduces the time to create the time-consuming objects by using the prototype pattern
  • This pattern reduces subclassing
  • This pattern adds and removes objects at runtime
  • This pattern configures the application with classes dynamically

让我们看看原型设计模式的 UML 类结构。

UML 类结构

下面的 UML diagram 显示了原型设计模式的所有组件:

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

原型设计模式的 UML 图

让我们看一下这些组件,如下所示:

  • Prototype: The Prototype is an interface. It is uses the clone method to create instances of this interface type.
  • ConcretePrototype: This is a concrete class of the Prototype interface to implement an operation to clone itself.
  • Client: This is a caller class to create a new object of a Prototype interface by calling a clone method of the prototype interface.

让我们看一个原型设计模式的示例实现。

原型设计模式的示例实现

我将创建一个抽象的 Account 类和扩展 Account 类的 concrete 类。 AccountCache 类被定义为下一步,它将帐户对象存储在 HashMap 中,并在请求时返回它们的克隆。创建一个实现 Clonable 接口的抽象类。

    package com.packt.patterninspring.chapter2.prototype.pattern;
    public abstract class Account implements Cloneable{
      abstract public void accountType();
      public Object clone() {
        Object clone = null;
        try {
          clone = super.clone();
        }
        catch (CloneNotSupportedException e) {
          e.printStackTrace();
        }
        return clone;
      }
    }

现在让我们创建扩展前一个类的具体类:

这是 CurrentAccount.java 文件:

    package com.packt.patterninspring.chapter2.prototype.pattern;
    public class CurrentAccount extends Account {
      @Override
      public void accountType() {
        System.out.println("CURRENT ACCOUNT");
      }
    }

以下是 SavingAccount.java 的外观:

    package com.packt.patterninspring.chapter2.prototype.pattern;
    public class SavingAccount extends Account{
      @Override
      public void accountType() {
        System.out.println("SAVING ACCOUNT");
      }
    }

让我们创建一个类来获取 AccountCache.java 文件中的具体类:

    package com.packt.patterninspring.chapter2.prototype.pattern;
    import java.util.HashMap;
    import java.util.Map;
    public class AccountCache {
       public static Map<String, Account> accountCacheMap =
           new HashMap<>();
       static{
         Account currentAccount = new CurrentAccount();
         Account savingAccount = new SavingAccount();
         accountCacheMap.put("SAVING", savingAccount);
         accountCacheMap.put("CURRENT", currentAccount);
       }
     }

PrototypePatternMain.java 是一个演示类,我们将使用它来测试设计模式 AccountCache 以获取 Account 对象通过传递一条信息,例如类型,然后调用 clone() 方法:

    package com.packt.patterninspring.chapter2.prototype
         .pattern;
    public class PrototypePatternMain {
      public static void main(String[] args) {
        Account currentAccount = (Account) 
          AccountCache.accountCacheMap.get("CURRENT").clone();
       currentAccount.accountType();
       Account savingAccount = (Account) 
         AccountCache.accountCacheMap.get("SAVING") .clone();
       savingAccount.accountType();
     }
   }

到目前为止,我们已经介绍了这一点,这很好。现在让我们看看下一个设计模式。

生成器设计模式

将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。 - GOF 设计模式

Builder 设计模式用于一步一步地构造一个复杂的对象,最后它会返回完整的对象。对象创建的逻辑和过程应该是通用的,以便您可以使用它来创建相同对象类型的不同具体实现。这种模式简化了复杂对象的构造,并且它对客户端调用者代码隐藏了对象构造的细节。使用此模式时,请记住您必须一次构建它,这意味着您必须将对象构建登录分成多个阶段,这与其他模式不同,例如 abstract 工厂和工厂方法模式,其中的对象在一个步骤中。

建造者模式的好处:

  • This pattern provides you with complete isolation between the construction and representation of an object
  • This pattern allows you to construct the object in multiple phases, so you have greater control over the construction process
  • This pattern provides the flexibility to vary an object's internal representation

UML 类结构

下面的 UML 图显示了 Builder 设计模式的所有 组件

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

Builder 设计模式的 UML 图:

  • Builder (AccountBuilder): This is an abstract class or interface for creating the details of an Account object.
  • ConcreteBuilder: This is an implementation to construct and assemble details of the account by implementing the Builder interface.
  • Director: This constructs an object using the Builder interface.
  • Product (Account): This represents the complex object under construction. AccountBuilder builds the account's internal representation and defines the process by which it's assembled.

在 Spring Framework 中实现 Builder 模式

Spring 框架在某些功能中实现了 Builder 设计模式透明。以下类基于 Spring Framework 中的 Builder 设计模式:

  • EmbeddedDatabaseBuilder
  • AuthenticationManagerBuilder
  • UriComponentsBuilder
  • BeanDefinitionBuilder
  • MockMvcWebClientBuilder

应该应用 Builder 模式的常见问题

在企业应用程序中,您可以应用构建器 pattern,其中已通过多个步骤完成了对象创建。在每个步骤中,您都会执行该过程的一部分。在这个过程中,你设置了一些必需的参数和一些可选的参数,经过最后一步,你会得到一个复杂的对象。

Builder 模式是一种对象创建软件设计模式。目的是抽象构造步骤,以便这些步骤的不同实现可以构造对象的不同表示。通常,Builder 模式用于根据复合模式构建产品。

Builder 设计模式的示例实现

在下面的代码示例中,我将 going 创建一个 Account 类,该类将 AccountBuilder 作为内部阶级。 AccountBuilder 类有一个创建此类实例的方法:

    package com.packt.patterninspring.chapter2.builder.pattern; 
    public class Account { 
      private String accountName; 
      private Long accountNumber; 
      private String accountHolder; 
      private double balance; 
      private String type; 
      private double interest; 
      private Account(AccountBuilder accountBuilder) { 
         super(); 
         this.accountName = accountBuilder.accountName; 
         this.accountNumber = accountBuilder.accountNumber; 
         this.accountHolder = accountBuilder.accountHolder; 
         this.balance = accountBuilder.balance; 
         this.type = accountBuilder.type; 
         this.interest = accountBuilder.interest; 
      } 
      //setters and getters 
       public static class AccountBuilder { 
         private final String accountName; 
         private final Long accountNumber; 
         private final String accountHolder; 
         private double balance; 
         private String type; 
         private double interest; 
         public AccountBuilder(String accountName, 
            String accountHolder, Long accountNumber) { 
            this.accountName = accountName; 
            this.accountHolder = accountHolder; 
            this.accountNumber = accountNumber; 
         } 
         public AccountBuilder balance(double balance) { 
            this.balance = balance; 
            return this; 
         } 
         public AccountBuilder type(String type) { 
            this.type = type; 
            return this; 
         } 
         public AccountBuilder interest(double interest) { 
            this.interest = interest; 
            return this; 
         } 
         public Account build() { 
            Account user =  new Account(this); 
            return user; 
         } 
       } 
       public String toString() { 
       return "Account [accountName=" + accountName + ", 
          accountNumber=" + accountNumber + ", accountHolder=" 
          + accountHolder + ", balance=" + balance + ", type="
          + type + ", interest=" + interest + "]"; 
       } 
    } 

AccountBuilderTest.java 是一个演示类,我们将使用它来测试设计模式。让我们看看如何通过将初始信息传递给对象来构建 Account 对象:

     package com.packt.patterninspring.chapter2.builder.pattern; 
     public class AccountBuilderTest { 
       public static void main(String[] args) { 
         Account account = new Account.AccountBuilder("Saving
            Account", "Dinesh Rajput", 1111l) 
              .balance(38458.32) 
              .interest(4.5) 
              .type("SAVING") 
              .build(); 
         System.out.println(account); 
       } 
     } 

您可以测试此文件并在控制台上查看输出:

读书笔记《spring-5-design-patterns》第 2 章 GOF 设计模式概述 - 核心设计模式

现在,我们已经看到了 Builder 设计模式。在即将到来的第3章中,结构和行为的考虑 模式, 我将探索 GOF 设计模式系列的另一部分。

概括


阅读本章后,读者现在应该对 GOF 创建设计模式的概述及其最佳实践有了一个很好的了解。我强调了在企业应用程序开发中不使用设计模式所带来的问题,以及 Spring 如何通过在应用程序中使用创建设计模式和良好实践来解决这些问题。在本章中,我只提到了 GOF 设计模式的三个主要类别中的一个创建设计模式类别。 Creational 设计模式用于创建对象实例,并且还使用 Factory、Abstract Factory、Builder、Prototype 和 Singleton 模式在企业应用程序中以特定方式在创建时应用约束。在下一章中,我们将看看 GOF 设计模式的其他类别——结构设计模式和行为设计模式。结构化设计模式用于通过处理类或对象的组合来设计企业应用程序的结构,从而降低应用程序的复杂性,提高应用程序的可重用性和性能。 Adapter 模式、Bridge 模式、Composite 模式、Decorator 模式、Facade 模式和 Flyweight 模式都属于这一类模式。行为设计模式描述了类或对象交互和分配责任的方式。属于这一类的模式特别关注对象之间的通信。让我们在下一章完成剩下的 GOF 模式。