vlambda博客
学习文章列表

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

第 3 章考虑结构和行为模式

您已经实现来自 GOF 模式系列的创建设计模式的说明和示例>第 2 章GOF 设计模式概述 - 核心设计模式。 现在,在本章中,您将获得一个概述GOF 设计模式的其他部分,它们是结构和行为设计模式,包括一些应用程序设计的最佳实践。您还将获得使用这些设计模式解决常见问题的概述。

在本章结束时,您将了解这些设计模式如何提供最佳解决方案来解决对象组合中的设计和开发相关问题以及在应用程序中的工作对象之间委派职责。您将获得有关 Spring Framework 如何在内部实现结构和行为设计模式以提供最佳企业解决方案的信息。

本章将涵盖以下几点:

  • Implementing the structural design patterns
  • Implementing the behavioral design patterns
  • J2EE design patterns

检查核心设计模式


让我们继续我们的 core 设计模式之旅:

  • Structural design pattern: Patterns under this category deal with the composition of classes or objects. In the enterprise application, there are two common techniques for reusing functionality in object-oriented systems as follows:
    • Inheritance: It is used to inherit commonly used states and behaviors from other classes.
    • Composition: It is used to compose the other objects as instance variables of classes. It defines ways to compose objects to obtain new functionalities.
  • Behavioral design pattern: Patterns under this category characterize the ways in which classes or objects interact with and distribute responsibility. These patterns define the methods of communication between the objects in the enterprise application. So here, you will learn how to use behavioral patterns to reduce complicated flow control. Furthermore, you will use behavioral patterns to encapsulate algorithms and dynamically select them at runtime.

结构设计模式

在上一节中,我们讨论了 creational 设计模式以及它们如何根据业务需求为对象创建提供最佳解决方案。创建型设计模式仅提供了在应用程序中创建对象的解决方案,以及这些对象如何在应用程序中为特定的业务目标相互合并,结构设计模式出现了。在本章中,我们将探索结构模式,以及这些模式如何用于定义对象之间的关系,无论是使用继承还是组合,用于应用程序的较大结构。结构模式允许您解决与构建对象之间的关系相关的许多问题。它们向您展示了如何以灵活和可扩展的方式将系统的不同部分粘合在一起。结构模式帮助您保证当其中一个部分发生变化时,整个结构不需要改变;在汽车中,您可以用不同的供应商更换轮胎,而不会影响汽车的其他部件。他们还向您展示了如何将系统中不适合(但您需要使用)的部分重铸成适合的部分。

适配器设计模式

将一个类的接口转换成客户期望的另一个接口。 Adapter 让那些因为接口不兼容而无法协同工作的类。 -GoF 设计模式:可重用的面向对象软件的要素

适配器设计模式属于结构化设计模式,根据这种设计模式,两个不兼容的类可以一起工作,而否则会因为接口不兼容而无法工作。此模式充当两个不兼容接口之间的桥梁。当应用程序的两个推断在其功能上不兼容时使用此模式,但需要将这些功能集成为业务需求。

有很多现实生活中我们可以使用适配器模式的例子。假设您有不同类型的电插头,例如圆柱形和矩形插头,如下图所示。假设满足电压要求,您可以使用中间的适配器将矩形插头插入圆柱形插座:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式
适配器模式的好处

让我们看一下在应用程序中使用适配器设计模式的以下好处

  • The adapter pattern allows you to communicate and interact with two or more incompatible objects
  • This pattern promotes the reusability of older existing functionalities in your application
适配器模式的常见要求

以下是此设计模式解决设计问题的common 要求:

  • If you are to use this pattern in your application, there is a need to use an existing class with an incompatible interface.
  • Another use of this pattern in your application is when you want to create a reusable class that collaborates with classes that have incompatible interfaces.
  • There are several existing subclasses to be used, but it's impractical to adapt their interface by sub classing each one. An object adapter can adapt the interface of its parent class.

让我们看看 Spring 如何在内部实现适配器设计模式。

Spring Framework中适配器设计模式的实现

Spring Framework 使用适配器 design 模式在整个框架中透明地实现许多功能。下面列出了一些基于 Spring Framework 中适配器设计模式的类:

  • JpaVendorAdapter
  • HibernateJpaVendorAdapter
  • HandlerInterceptorAdapter
  • MessageListenerAdapter
  • SpringContextResourceAdapter
  • ClassPreProcessorAgentAdapter
  • RequestMappingHandlerAdapter
  • AnnotationMethodHandlerAdapter
  • WebMvcConfigurerAdapter

适配器模式的 UML 图

让我们理解前面的 UML diagram,它说明了适配器设计模式的组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式
  • The Target Interface: This is the desired interface class that will be used by the clients
  • The Adapter class: This class is a wrapper class that implements the desired target interface and modifies the specific request available from the Adaptee class
  • The Adaptee class: This is the class that is used by the Adapter class to reuse the existing functionalities and modify them for desired use
  • Client: This class will interact with the Adapter class

让我们看一下适配器设计模式的以下示例实现。

适配器设计模式的示例实现

我将创建一个示例,显示适配器设计模式的实际演示,所以让我们讨论这个示例,我正在创建基于通过支付网关进行支付的示例。假设我有一个旧的支付网关,也有最新的高级支付网关,并且两个网关彼此无关,所以我的要求是,我想从旧的支付网关迁移到高级支付网关,同时更改我现有的源代码.我正在创建一个适配器类来解决这个问题。这个适配器类作为两个不同支付网关之间的桥梁,让我们看看下面的代码:

现在让我们为旧支付网关创建一个接口:

    package com.packt.patterninspring.chapter3.adapter.pattern; 
    import com.packt.patterninspring.chapter3.model.Account; 
    public interface PaymentGateway { 
      void doPayment(Account account1, Account account2); 
    } 

现在让我们为旧的支付网关 PaymentGateway.java 创建一个实现类:

    package com.packt.patterninspring.chapter3.adapter.pattern; 
    import com.packt.patterninspring.chapter3.model.Account; 
    public class PaymentGatewayImpl implements PaymentGateway{ 
      @Override 
      public void doPayment(Account account1, Account account2){ 
         System.out.println("Do payment using Payment Gateway"); 
      } 
    } 

以下接口及其实现为支付网关提供了新的高级功能:

    package com.packt.patterninspring.chapter3.adapter.pattern; 
    public interface AdvancedPayGateway { 
      void makePayment(String mobile1, String mobile2); 
    } 

现在让我们为预付款网关接口创建一个实现类:

    package com.packt.patterninspring.chapter3.adapter.pattern; 
    import com.packt.patterninspring.chapter3.model.Account; 
    public class AdvancedPaymentGatewayAdapter implements 
       AdvancedPayGateway{ 
      private PaymentGateway paymentGateway; 
      public AdvancedPaymentGatewayAdapter(PaymentGateway
         paymentGateway) { 
        this.paymentGateway = paymentGateway; 
      } 
      public void makePayment(String mobile1, String mobile2) { 
         Account account1 = null;//get account number by 
             mobile number mobile  
         Account account2 = null;//get account number by 
            mobile number mobile  
         paymentGateway.doPayment(account1, account2); 
      } 
    } 

让我们看一下这个模式的演示类,如下所示:

    package com.packt.patterninspring.chapter3.adapter.pattern; 
    public class AdapterPatternMain { 
      public static void main(String[] args) { 
        PaymentGateway paymentGateway = new PaymentGatewayImpl(); 
        AdvancedPayGateway advancedPayGateway = new 
           AdvancedPaymentGatewayAdapter(paymentGateway); 
        String mobile1 = null; 
        String mobile2 = null; 
        advancedPayGateway.makePayment(mobile1, mobile2); 
      } 
    } 

在前面的类中,我们将旧的支付网关对象作为 PaymentGateway 接口,但是我们将这个旧的支付网关实现转换为高级形式的支付网关,使用 AdvancedPaymentGatewayAdapter 适配器类。让我们运行这个演示类,看看输出如下:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

现在我们已经了解了适配器设计模式,让我们转向它的不同变体——桥接设计模式。

桥接设计模式

将抽象与其实现分离,以便两者可以独立变化 - GoF 设计模式:可重用的面向对象软件的元素

在软件工程中,最流行的概念之一是优先组合而不是继承。桥接设计模式推广了这个流行的概念。与适配器模式类似,该模式也属于 GoF 设计模式的结构设计模式家族。桥接模式的方法是将客户端代码使用的抽象与其实现分离;这意味着它将抽象及其实现分离为单独的类层次结构。而且,桥接模式更喜欢组合而不是继承,因为继承并不总是灵活的,并且它破坏了封装,因此在实现者中所做的任何更改都会影响客户端代码使用的抽象。

桥接提供了在软件开发中两个不同的独立组件之间进行通信的方式,桥接结构为您提供了一种将抽象类和实现类解耦的方法。因此,在实现类或实现者(即接口)中所做的任何更改都不会影响抽象类或其精炼的抽象类。它通过在接口和抽象之间使用组合来实现这一点。桥接模式使用接口作为抽象类的具体类和该接口的实现类之间的桥梁。您可以对这两种类型的类进行更改,而不会对客户端代码产生任何影响。

桥接模式的好处

以下是 Bridge 设计模式的好处:

  • The Bridge design pattern allows you to separate the implementation and the abstraction
  • This design pattern provides the flexibility to change both types of classes without side effects in the client code
  • This design pattern allows the hiding of actual implementation details from the client by using abstraction between them
桥接设计模式解决的常见问题

以下是 Bridge 设计模式解决的常见问题

  • Removes a permanent binding between the functional abstraction and its implementation
  • You can make changes to the implementing classes without affecting the abstraction and client code
  • You can extend the abstraction and its implementation using subclasses
在 Spring Framework 中实现 Bridge 设计模式

以下 Spring 模块基于 Bridge 设计模式:

  • ViewRendererServlet: It is a bridge servlet, mainly for Portlet MVC support
  • The Bridge design pattern: The Bridge design pattern is used in the Spring logging process

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

桥接设计模式的示例实现

让我们看下面的示例,我们将在其中演示桥接设计模式的使用。假设您要开立两种类型的账户,一种是储蓄账户,而其他 是银行系统中的活期账户。

不使用 Bridge 设计模式的系统

让我们看一个不使用桥接设计模式的示例。在下图中,您可以看到 Bank 和 Account 接口之间的关系:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

不使用桥接设计模式的系统

让我们在不使用桥接设计模式的情况下创建一个设计。首先创建一个接口或抽象类,Bank。然后创建其派生类:IciciBankHdfcBank。要在银行开户,首先要确定账户类别的类型——储蓄账户Current Account,这些类扩展了特定的银行类(HdfcBank<强>IciciBank)。此应用程序中有一个简单的深层继承层次结构。那么这个设计和上图相比有什么问题呢?你会注意到,在这个设计中,有两个部分,一个是抽象部分,另一个是实现部分。客户端代码与抽象部分交互。客户端代码只有在您更新抽象部分时才能访问实现部分的新更改或新功能,这意味着部分、抽象和实现是紧密耦合的。

现在让我们看看如何使用 Bridge 设计模式改进这个示例:

具有桥梁设计模式的系统

在下图中,我们使用 Bridge 设计 pattern Bank 和 Account 接口之间的关系跨度>:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

使用桥接设计模式的系统

桥接设计模式的 UML 结构

让我们看一下桥设计模式如何解决这些设计问题的以下,如我们未使用桥设计模式的示例所示。桥接模式将抽象和实现分为两个类层次结构:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

桥接设计模式的 UML

我们有一个 Account 接口,它充当桥梁实现者和具体类 SavingAccountCurrentAccount 实现 Account 接口。 Bank 是一个抽象类,它将使用 Account 对象。

让我们创建一个桥实现器接口。

以下是 Account.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public interface Account { 
      Account openAccount(); 
      void accountType(); 
    } 

创建具体的桥实现类来实现 implementer 接口。让我们创建一个 SavingAccount 类作为 Account 的实现。

以下是 SavingAccount.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class SavingAccount implements Account { 
      @Override 
      public Account openAccount() { 
         System.out.println("OPENED: SAVING ACCOUNT "); 
         return new SavingAccount(); 
      } 
      @Override 
      public void accountType() { 
        System.out.println("##It is a SAVING Account##"); 
      } 
    } 

创建一个实现 Account 接口的 CurrentAccount 类。

以下是 CurrentAccount.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class CurrentAccount implements Account { 
      @Override 
      public Account openAccount() { 
        System.out.println("OPENED: CURRENT ACCOUNT "); 
        return new CurrentAccount(); 
      } 
      @Override 
      public void accountType() { 
        System.out.println("##It is a CURRENT Account##"); 
      } 
    } 

在 Bridge 设计模式中创建抽象,但首先,创建接口 Bank

以下是 Bank.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public abstract class Bank { 
      //Composition with implementor 
      protected Account account; 
      public Bank(Account account){ 
         this.account = account; 
      } 
      abstract Account openAccount(); 
    } 

让我们实现 Bank 接口的第一个抽象,并查看以下 Bank 接口的实现类。

以下是 IciciBank.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class IciciBank extends Bank { 
      public IciciBank(Account account) { 
        super(account); 
      } 
      @Override 
      Account openAccount() { 
        System.out.print("Open your account with ICICI Bank"); 
        return account; 
      } 
    } 

让我们实现 Bank 接口的第二个抽象,看看下面的 Bank 接口的实现类。

以下是 HdfcBank.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
      public class HdfcBank extends Bank { 
        public HdfcBank(Account account) { 
          super(account); 
        } 
        @Override 
        Account openAccount() { 
          System.out.print("Open your account with HDFC Bank"); 
          return account; 
        } 
      } 

创建一个桥接设计模式的演示类。

以下是 BridgePatternMain.java 文件:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class BridgePatternMain { 
      public static void main(String[] args) { 
         Bank icici = new IciciBank(new CurrentAccount()); 
         Account current = icici.openAccount(); 
         current.accountType(); 
         Bank hdfc = new HdfcBank(new SavingAccount()); 
         Account saving = hdfc.openAccount(); 
         saving.accountType(); 
      } 
    } 

让我们运行这个演示类并在控制台中查看以下输出:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

现在我们已经了解了桥接设计模式,让我们转向它的不同变体——复合设计模式。

复合设计模式

将对象组合成树形结构以表示部分-整体层次结构。 Composite 让客户可以统一处理单个对象和对象的组合。 -GoF 设计模式

在软件工程中,复合pattern属于结构设计模式。根据这种模式,一组相同类型的对象被客户端视为一个对象。复合设计模式背后的思想是将一组对象组合成一个树形结构,以表示一个更大的结构化应用程序的一个模块。并且这种结构对于客户端来说是一个单一的单元或者统一的instance

复合设计模式背后的动机是将系统中的对象分组为树结构,树结构是节点叶子和分支的组合。在树形结构中,节点有许多叶子和其他节点。叶没有任何东西,这意味着树中没有叶的孩子。叶被视为树结构数据的端点。

我们看下图,它以节点和叶子的形式表示树结构中的数据:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

使用节点和叶子的树结构数据

复合模式解决的常见问题

作为开发人员,设计一个应用程序是比较困难的,以便 客户端可以在整个应用程序中统一访问您的对象,即使该对象是对象的组合或单个对象。这种设计模式解决了困难,并允许您以这样一种方式设计对象,即您可以将该对象用作对象的组合和单个对象。

这种模式解决了创建分层树结构时面临的挑战,为客户提供了一种访问和操作树中对象的统一方式。复合图案是不错的选择;在这种情况下,将基元和复合体视为同质的并不那么复杂。

复合设计模式的UML结构

复合设计模式是基于将相似类型的对象composition组成树结构,正如你知道的,每棵树都有分支、节点和叶子三个主要部分。因此,让我们看一下此设计模式中使用的以下术语。

组件:它基本上是树的一个分支,该分支还有其他分支、节点和叶子。组件为所有组件提供抽象,包括复合对象。在组合模式中,组件 基本上声明为对象的接口。

Leaf:它是一个实现所有组件方法的对象。

Composite:表示为树形结构中的一个节点,还有其他节点和叶子,表示一个复合组件。它具有添加子对象的方法,即它表示相同类型对象的集合。它有其他子组件方法。

让我们看一下此设计模式的以下 UML 图:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

复合设计模式的 UML 图

复合设计模式的好处

  • This pattern provides the flexibility to add new component to process dynamically, with change in the existing components
  • This pattern allows you to create a class hierarchy that contains individual and composite objects
复合设计模式的示例实现

在下面的例子中,我实现一个Account接口,它可以是一个SavingAccountCurrentAccount 或多个帐户的组合。我有一个 CompositeBankAccount 类,它充当复合模式参与者类。让我们看一下此示例的以下代码。

创建一个将被视为组件的 Account 接口:

    public interface Account { 
      void accountType(); 
    } 

创建一个 SavingAccount 类和 CurrentAccount 类作为组件的实现,它也将被视为叶子:

以下是 SavingAccount.java 文件:

    public class SavingAccount implements Account{ 
      @Override 
      public void accountType() { 
        System.out.println("SAVING ACCOUNT"); 
      } 
    } 

以下是 CurrentAccount.java 文件:

    public class CurrentAccount implements Account { 
      @Override 
      public void accountType() { 
         System.out.println("CURRENT ACCOUNT"); 
      } 
    } 

创建一个 CompositeBankAccount 类,该类将被视为一个 Composite 并实现 Account 接口:

以下是 CompositeBankAccount.java 文件:

     package com.packt.patterninspring.chapter3.composite.pattern; 
     import java.util.ArrayList; 
     import java.util.List; 
     import com.packt.patterninspring.chapter3.model.Account; 
     public class CompositeBankAccount implements Account { 
       //Collection of child accounts. 
       private List<Account> childAccounts = new ArrayList<Account>(); 
       @Override 
       public void accountType() { 
         for (Account account : childAccounts) { 
               account.accountType(); 
         } 
       } 
       //Adds the account to the composition. 
          public void add(Account account) { 
            childAccounts.add(account); 
          } 
          //Removes the account from the composition. 
          public void remove(Account account) { 
            childAccounts.remove(account); 
         } 
       } 

创建一个也将被视为客户端的 CompositePatternMain 类:

以下是 CompositePatternMain.java 文件:

    package com.packt.patterninspring.chapter3.composite.pattern; 
    import com.packt.patterninspring.chapter3.model.CurrentAccount; 
    import com.packt.patterninspring.chapter3.model.SavingAccount; 
    public class CompositePatternMain { 
      public static void main(String[] args) { 
         //Saving Accounts 
         SavingAccount savingAccount1 = new SavingAccount(); 
         SavingAccount savingAccount2 = new SavingAccount(); 
         //Current Account 
         CurrentAccount currentAccount1 = new CurrentAccount(); 
         CurrentAccount currentAccount2 = new CurrentAccount(); 
         //Composite Bank Account 
         CompositeBankAccount compositeBankAccount1 = new
         CompositeBankAccount(); 
         CompositeBankAccount compositeBankAccount2 = new
         CompositeBankAccount(); 
         CompositeBankAccount compositeBankAccount = new
         CompositeBankAccount(); 
         //Composing the bank accounts 
         compositeBankAccount1.add(savingAccount1); 
         compositeBankAccount1.add(currentAccount1); 
         compositeBankAccount2.add(currentAccount2); 
         compositeBankAccount2.add(savingAccount2); 
         compositeBankAccount.add(compositeBankAccount2); 
         compositeBankAccount.add(compositeBankAccount1); 
         compositeBankAccount.accountType(); 
      } 
    } 

让我们运行这个演示类并在控制台中查看以下输出:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

现在我们已经讨论了复合设计模式,让我们转向装饰器设计模式。

装饰器设计模式

动态地为对象附加额外的职责。装饰器为扩展功能提供了一种灵活的替代子类的方法。 - GOF 设计模式

在软件工程中,所有 GOF 结构模式的共同意图是在灵活的 enterprise 应用程序中简化对象和类之间的复杂关系。装饰器模式是其中一种特殊类型的设计模式,属于结构设计模式,它允许您在运行时动态或静态地添加和删除单个对象的行为,而无需更改其他关联对象的现有行为。班级。此设计模式在不违反单一职责原则或面向对象编程的 SOLID 原则的情况下做到这一点。

这种设计模式使用组合而不是对象关联的继承;它允许您将功能划分为具有独特关注领域的不同具体类。

装饰器设计模式的好处

  • This pattern allows you to extend functionality dynamically and statically without altering the structure of existing objects
  • By using this pattern, you could add a new responsibility to an object dynamically
  • This pattern is also known as Wrapper
  • This pattern uses the compositions for object relationships to maintain SOLID principles
  • This pattern simplifies coding by writing new classes for every new specific functionality rather than changing the existing code of your application
装饰器模式解决的常见问题

在企业应用程序中,存在业务需求,或者可能存在通过添加新功能来扩展产品行为的未来计划。为此,您可以使用继承来扩展对象的行为。但是继承应该在编译时完成,并且该类的其他实例也可以使用方法。由于代码修改,违反了开闭原则。为避免这种违反 SOLID 原则的行为,您可以动态地将新职责附加到对象。这是装饰器设计模式出现的情况,并以非常灵活的方式解决了这个问题。让我们看一下如何将这种设计模式实施到实际案例研究中的以下示例。

考虑到一家银行为客户提供了多个具有不同利益的账户。它将客户分为三类——老年人、特权阶层和年轻人。该银行推出了老年人储蓄账户计划——如果他们在这家银行开设储蓄账户,他们将获得最高1000美元的医疗保险。同样,银行还为特权客户提供高达 1,600 美元的意外保险和 84 美元的透支额度。没有适合年轻人的计划。

为了满足新的需求,我们可以添加 SavingAccount 的新子类;每个代表一个储蓄账户,带有额外的好处作为装饰,这就是我们现在的设计:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

不使用装饰器设计模式的继承应用程序设计

这个设计会非常复杂,因为我会在 SavingAccount 中添加更多的福利方案,但是当银行为 CurrentAccount?显然,这种设计是有缺陷的,但这是装饰器模式的理想用例。此模式允许您添加运行时动态行为。在这种情况下,我将创建一个抽象的 AccountDecorator 类来实现 Account 。此外,我将创建 SeniorCitizen 类和 Privilege 类,它扩展了AccountDecorator,因为young没有任何额外的好处,所以SavingAccount类没有扩展AccountDecorator。这就是设计的方式:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

使用装饰器设计模式的组合应用程序设计

上图遵循装饰器设计模式,将 AccountDecorator 创建为 Decorator 在这种模式下,重点关注重要的事情来观察 AccountAccountDecorator< 之间的关系/strong>。这种关系如下:

  • Is-a relationship between the AccountDecorator and Account, that is, inheritance for the correct type
  • Has-a relationship between the AccountDecorator and Account, that is, composition in order to add new behavior without changing the existing code

我们来看看UML结构

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

装饰器设计模式的 UML

参与此模式的类和对象是:

  • Component (Account): It is an interface for objects that can have responsibilities added to them dynamically
  • ConcreteComponent (SavingAccount): It is a concrete class of component interface and it defines an object to which additional responsibilities can be attached
  • Decorator (AccountDecorator): It has a reference to a Component object and defines an interface that conforms to the interface of the component
  • ConcreteDecorator (SeniorCitizen and Privilege): It is a concrete implementation of Decorator and it adds responsibilities to the component
实现装饰器模式

让我们看看下面的代码来演示装饰器设计模式。

创建一个组件类:

以下是 Account.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public interface Account { 
       String getTotalBenefits(); 
    } 

创建具体的组件类:

以下是 SavingAccount.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public class SavingAccount implements Account { 
      @Override 
      public String getTotalBenefits() { 
         return "This account has 4% interest rate with per day
           $5000 withdrawal limit"; 
      } 
    } 

让我们为 Account 组件创建另一个具体的类:

以下是 CurrentAccount.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public class CurrentAccount implements Account { 
      @Override 
      public String getTotalBenefits() { 
         return "There is no withdrawal limit for current account"; 
      } 
    } 

让我们为 Account 组件创建一个 Decorator 类。此装饰器类将其他运行时行为应用于 Account 组件类。

以下是 AccountDecorator.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public abstract class AccountDecorator implements Account { 
      abstract String applyOtherBenefits(); 
    } 

让我们创建一个 ConcreteDecorator 类来实现 AccountDecorator 类。以下类 SeniorCitizen 扩展了 AccountDecorator 类以访问其他运行时行为,例如 applyOtherBenefits()

以下是 SeniorCitizen.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public class SeniorCitizen extends AccountDecorator { 
      Account account; 
      public SeniorCitizen(Account account) { 
         super(); 
         this.account = account; 
      } 
      public String getTotalBenefits() { 
         return account.getTotalBenefits() + " other benefits are 
             "+applyOtherBenefits(); 
      } 
      String applyOtherBenefits() { 
         return " an medical insurance of up to $1,000 for Senior 
         Citizen"; 
      } 
    } 

让我们创建另一个 ConcreteDecorator 类来实现 AccountDecorator 类。以下类 Privilege 扩展了 AccountDecorator 类以访问其他运行时行为,例如 applyOtherBenefits(< /代码>)。

以下是 Privilege.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public class Privilege extends AccountDecorator { 
      Account account; 
      public Privilege(Account account) { 
         this.account = account; 
      } 
      public String getTotalBenefits() { 
         return account.getTotalBenefits() + " other benefits are    
            "+applyOtherBenefits(); 
      } 
      String applyOtherBenefits() { 
        return " an accident insurance of up to $1,600 and
           an overdraft facility of $84"; 
        } 
      } 

现在让我们编写一些测试代码来看看装饰器模式在运行时是如何工作的:

以下是 DecoratorPatternMain.java 文件:

    package com.packt.patterninspring.chapter3.decorator.pattern; 
    public class DecoratorPatternMain { 
      public static void main(String[] args) { 
         /*Saving account with no decoration*/ 
         Account basicSavingAccount = new SavingAccount(); 
         System.out.println(basicSavingAccount.getTotalBenefits()); 
         /*Saving account with senior citizen benefits decoration*/ 
         Account seniorCitizenSavingAccount = new SavingAccount(); 
         seniorCitizenSavingAccount = new 
            SeniorCitizen(seniorCitizenSavingAccount); 
         System.out.println
        (seniorCitizenSavingAccount.getTotalBenefits()); 
         /*Saving account with privilege decoration*/ 
         Account privilegeCitizenSavingAccount = new SavingAccount(); 
         privilegeCitizenSavingAccount = new
            Privilege(privilegeCitizenSavingAccount); 
         System.out.println
        (privilegeCitizenSavingAccount.getTotalBenefits()); 
      } 
    } 

让我们运行这个演示类并在控制台中查看以下输出:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

Spring 框架中的装饰器设计模式

Spring Framework 使用装饰器设计模式来构建重要的功能,例如事务、缓存同步和与安全相关的任务。让我们看一下 Spring 透明地实现此模式的一些功能:

  • Weaving the advice into the Spring application. It uses the Decorator pattern via the CGLib proxy. It works by generating a subclass of the target class at runtime.
  • BeanDefinitionDecorator : It is used to decorate the bean definition via applied custom attributes.
  • WebSocketHandlerDecorator: It is used to decorate a WebSocketHandler with additional behaviors.

现在让我们转向另一种 GOF 设计模式——Facade 设计模式。

立面设计模式

为子系统中的一组接口提供统一的接口。 Facade 定义了一个更高级别的接口,使子系统更易于使用。 - GOF 设计模式

Facade 设计模式只不过是一个interface 接口,用于简化 客户端代码和子系统类之间的交互。该设计属于 GOF 结构设计模式。

立面图案的好处:

  • This pattern reduces the complexities for clients to interact with subsystems
  • This pattern consolidates all the business services as single interfaces to make them more understandable
  • This pattern reduces dependencies of client code on the inner workings of a system
知道何时使用外观模式

假设你正在设计一个系统,这个系统有非常多的独立类,还有一组服务要实现。这个系统将非常复杂,因此外观模式出现了,它降低了更大系统的复杂性,并简化了客户端代码与大型复杂系统子系统中的一组类的交互。

假设您要开发一个银行企业应用程序,其中包含大量服务来执行一项任务,例如 AccountService 用于获取 Account by accountIdPaymentService 用于支付网关服务,TransferService 用于从一个账户转移到另一个账户的金额。应用程序的客户端代码与所有这些服务交互以将资金从一个帐户转移到另一个帐户。这就是不同客户如何与银行系统的金额转移过程进行交互的方式。如下图所示,这里可以看到直接与子系统类交互的客户端代码,并且客户端也应该知道子系统类的内部工作,所以这完全违反了 SOLID 设计原则,因为客户端代码是紧耦合的使用银行应用程序的子系统类:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

没有外观设计模式的银行应用程序子系统

与其客户端代码直接与子系统的类进行交互,您可以多引入一个接口,使子系统更易于使用,如下图所示。该接口称为 Facade 接口,它基于 Facade 模式,是与子系统交互的一种简单方式:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

具有外观设计模式的银行应用程序子系统

实现外观设计模式

让我们看看 以下 清单来演示 Facade 设计模式。

为您的银行应用程序创建子系统服务类:让我们看一下子系统的以下 PaymentService 类。

以下是 PaymentService.java 文件:

    package com.packt.patterninspring.chapter3.facade.pattern; 
    public class PaymentService { 
      public static boolean doPayment(){ 
         return true; 
      } 
    } 

让我们为子系统创建另一个服务类 AccountService。

以下是 AccountService.java 文件:

   package com.packt.patterninspring.chapter3.facade.pattern; 
   import com.packt.patterninspring.chapter3.model.Account; 
   import com.packt.patterninspring.chapter3.model.SavingAccount; 
   public class AccountService { 
     public static Account getAccount(String accountId) { 
        return new SavingAccount(); 
     } 
   } 

让我们为子系统创建另一个服务类 TransferService。

以下是 TransferService.java 文件:

    package com.packt.patterninspring.chapter3.facade.pattern; 
    import com.packt.patterninspring.chapter3.model.Account; 
    public class TransferService { 
      public static void transfer(int amount, Account fromAccount,
            Account toAccount) { 
        System.out.println("Transfering Money"); 
      } 
    } 

创建一个与子系统交互的 Facade Service 类:让我们看一下子系统的以下 Facade 接口,然后将这个 Facade 接口实现为应用程序中的全局银行服务。

以下是 BankingServiceFacade.java 文件:

    package com.packt.patterninspring.chapter3.facade.pattern; 
    public interface BankingServiceFacade { 
       void moneyTransfer(); 
    } 

以下是 BankingServiceFacadeImpl.java 文件:

    package com.packt.patterninspring.chapter3.facade.pattern; 
    import com.packt.patterninspring.chapter3.model.Account; 
    public class BankingServiceFacadeImpl implements 
        BankingServiceFacade{ 
      @Override 
      public void moneyTransfer() { 
         if(PaymentService.doPayment()){ 
               Account fromAccount = AccountService.getAccount("1"); 
               Account toAccount   = AccountService.getAccount("2"); 
               TransferService.transfer(1000, fromAccount, toAccount); 
         } 
      } 
    } 

创建门面的客户端:

以下是 FacadePatternClient.java 文件:

    package com.packt.patterninspring.chapter3.facade.pattern; 
    public class FacadePatternClient { 
      public static void main(String[] args) { 
        BankingServiceFacade serviceFacade = new 
          BankingServiceFacadeImpl(); 
        serviceFacade.moneyTransfer(); 
      } 
    } 
外观设计模式的 UML 结构

参与此模式的类和 objects 是:

  • Facade (BankingServiceFacade)

这是一个 Facade 接口,它知道哪些子系统类负责一个请求。该接口负责将客户端请求委托给适当的子系统对象。

  • Subsystem classes (AccountService, TransferService, PaymentService)

这些接口实际上是银行流程系统应用程序的子系统功能。这些负责处理由 Facade 对象分配的进程。此类别中的任何接口都没有对 Facade 对象的引用;他们没有 Facade 的实现细节。这些完全独立于 Facade 对象。

让我们看一下此模式的以下 UML 图:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

外观设计模式的 UML 图

Spring 框架中的外观模式

在企业应用中,如果你工作在Spring应用中,Facade模式通常用在应用的业务服务层来整合所有的服务。您还可以在持久层上的 DAO 上应用这种模式。

现在我们已经了解了 Facade 设计模式,让我们转向它的另一种变体——代理设计模式。

代理设计模式

为另一个对象提供代理或占位符以控制对其的访问。 -GOF 设计模式

代理设计模式provides一个类的对象具有另一个类的功能。该模式属于 GOF 设计模式的结构设计模式。此设计模式的intent 是为外部世界提供另一个类的替代类及其功能。

代理模式的目的

让我们看看以下点:

  • This pattern hides the actual object from the outside world.
  • This pattern can improve the performance because it is creating an object on demand.
代理设计模式的 UML 结构

让我们看看这个模式的 following UML 图:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

代理设计模式的 UML 图

现在让我们看看这个 UML 图的不同组件:

  • Subject: Actual interface to be implemented by Proxy and RealSubject.
  • RealSubject: Real implementation of Subject. It is a real object that represented by the proxy.
  • Proxy: It is a proxy object and it is also the implementation of the real object Subject. It maintains the references to the real object.
实现代理设计模式

让我们看一下以下代码来演示代理模式。

创建主题。

以下是 Account.java 文件:

    public interface Account { 
      void accountType(); 
    } 

创建一个实现主题的RealSubject 类,让我们将以下类视为代理设计模式的RealSubject 类。

以下是 SavingAccount.java 文件:

    public class SavingAccount implements Account{ 
       public void accountType() { 
          System.out.println("SAVING ACCOUNT"); 
       } 
    } 

创建一个代理类,它实现了主题并拥有真实的主题

以下是 ProxySavingAccount.java 文件:

    package com.packt.patterninspring.chapter2.proxy.pattern; 
    import com.packt.patterninspring.chapter2.model.Account; 
    import com.packt.patterninspring.chapter2.model.SavingAccount; 
    public class ProxySavingAccount implements Account{ 
      private Account savingAccount; 
      public void accountType() { 
         if(savingAccount == null){ 
               savingAccount = new SavingAccount(); 
         } 
         savingAccount.accountType(); 
      }  
    } 
Spring 框架中的代理模式

Spring Framework 透明地使用 Spring AOP 模块中的 Proxy 设计模式。正如我在 第 1 章 中所讨论的,Spring Framework 5.0 和设计模式入门。在 Spring AOP 中,您创建对象的代理以在 Spring 应用程序的切点上应用横切关注点。在 Spring 中,其他模块也实现了 Proxy 模式,例如 RMI、Spring 的 HTTP Invoker、Hessian 和 Burlap。

让我们看下关于行为设计模式及其底层模式和示例的部分。

行为设计模式

Behavioral 设计模式的意图是一组对象之间的交互和协作,以执行单个对象无法单独执行的任务。对象之间的交互应该是松散耦合的。此类别下的模式描述了类或对象交互和分配责任的方式。让我们在下一节中了解行为设计模式的不同变体。

责任链设计模式

通过让多个对象有机会处理请求来避免将请求的发送者与其接收者耦合。链接接收对象并沿链传递请求,直到对象处理它。 -GOF 设计模式

责任链设计模式属于 GOF 模式家族的 Behavioral 设计模式。根据这种模式,request 的发送者和接收者是分离的。发送者向接收者链发送请求,链中的任何一个接收者都可以处理该请求。在此模式中,接收器对象具有另一个接收器对象的引用,因此如果它不处理请求,则它将相同的请求传递给另一个接收器对象。

例如,在银行系统中,您可以使用任何 ATM 在任何地方提取资金,因此它是责任链设计模式的活生生的例子之一。

这种模式有以下好处:

  • This pattern reduces the coupling between sender and receiver objects in the system to handle a request.
  • This pattern is more flexible to assign the responsibility to another referenced object.
  • This pattern makes a chain of objects using composition, and this set of objects work as a single unit.

让我们看看下面的 UML 图,它显示了责任链设计模式的所有组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

责任链设计模式的UML图

 

  • Handler: This is an abstract class or interface in the system to handle request.
  • ConcreteHandler: These are concrete classes which implement Handler to handle the request, or it passes same request to the next successor of the handler chain.
  • Client: It is main application class to initiate the request to the handler objects on the chain.
Spring框架中的责任链模式

Spring Security 项目在 Spring Framework 中实现了Chain 责任模式。 Spring Security 允许您通过使用安全过滤器链在应用程序中实现身份验证和授权功能。这是一个高度可配置的框架。由于责任链设计模式,您可以使用此过滤器链添加自定义过滤器以自定义功能。

现在我们已经看到了责任链设计模式,让我们转向它的另一个变体——命令设计模式。

命令设计模式

将请求封装为一个对象,从而让您参数化具有不同请求的客户端、排队或记录请求,并支持可撤消的操作 -GOF 设计模式

命令设计模式属于 GOF 模式的 Behavioral 模式系列,该模式是一种非常简单的数据驱动模式,它允许您将请求数据封装到一个对象中并将该对象作为命令传递到调用者方法,并将命令作为另一个对象返回给调用者。

下面列出了使用命令模式的好处:

  • This pattern enables you to transfer data as an object between the system components sender and receiver.
  • This pattern allows you to parameterize objects by an action to perform.
  • You could easily add new commands in the system without changing existing classes.

让我们看看下面的 UML 图,它显示了命令设计模式的所有组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

命令设计模式的 UML 图

  • Command: It is an interface or abstract class having an action to perform in the system.
  • ConcreteCommand: It is a concrete implementation of the Command interface and defining an action will be performed.
  • Client: This is a main class, it creates a ConcreteCommand object and sets its receiver.
  • Invoker: It is a caller to invoke the request to carry the command object.
  • Receiver: It is simple handler method which performs the actual operation by ConcreteCommand.
Spring Framework 中的命令设计模式

Spring MVC 在 Spring Framework 中实现了 Command 设计模式。在使用 Spring Framework 的企业应用程序中,您经常会看到通过使用 Command 对象来应用 Command 模式的概念。

现在我们已经了解了命令设计模式,让我们转向它的另一个变体——解释器设计模式。

解释器设计模式

给定一种语言,定义其语法的表示以及使用该表示来解释该语言中的句子的解释器。 -GOF 设计模式

解释器设计模式允许您在编程中解释 expression 语言以定义其语法的表示。这种类型的模式属于 GOF 模式的行为设计模式系列。

下面列出了使用解释器模式的好处:

  • This pattern allows you to change and extend the grammar easily.
  • Using the expression language is very easy

让我们看看下面的 UML 图显示了解释器设计模式的所有组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

解释器设计模式的 UML 图

  • AbstractExpression: It is an interface to execute a task by using interpret() operation.
  • TerminalExpression: It is an implementation of above interface and it implements interpret()operation for terminal expressions.
  • NonterminalExpression: It is also an implementation of above interface and it implements interpret() operation for non-terminal expressions.
  • Context: It is a String expression and contains information that is global to the interpreter.
  • Client: It is the main class to invoke the Interpret operation.
Spring Framework 中的解释器设计模式

Spring 框架中,解释器模式与 Spring 表达式语言 (<强>SpEL)。 Spring 在 Spring 3.0 中添加了这个新特性,您可以在使用 Spring Framework 的 enterprise 应用程序中使用它。

现在我们已经了解了解释器设计模式,让我们转向它的另一个变体——迭代器设计模式。

迭代器设计模式

提供一种顺序访问聚合对象的元素而不暴露其底层表示的方法。 -GOF 设计模式

这是编程语言中非常常用使用的设计模式,就像在 Java 中一样。该模式来自 GOF 模式的行为设计模式家族。此模式允许您按顺序访问集合对象中的项目,而无需了解其内部表示。

以下是迭代器模式的好处:

  • Easily access the items of the collection.
  • You can use multiple to access the item from the collection because it support lot of variations in the traversal.
  • It provides a uniform interface for traversing different structures in a collection.

让我们看看下面的 UML 图显示了迭代器设计模式的所有组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

迭代器设计模式的 UML 图

  • Iterator: It is an interface or abstract class for accessing and traversing items of the collections.
  • ConcreteIterator: It is an implementation of the Iterator interface.
  • Aggregate: It is an interface to create an Iterator object.
  • ConcreteAggregate: It is the implementation of the Aggregate interface, it implements the Iterator creation interface to return an instance of the proper ConcreteIterator.
Spring 框架中的迭代器设计模式

Spring 框架还通过 CompositeIterator扩展 Iterator 模式。主要是在 Java 的 Collection Framework 中使用的这种模式,用于按顺序迭代元素。

现在我们已经了解了迭代器设计模式,让我们转向它的另一个变体——观察者设计模式。

观察者设计模式

在对象之间定义一对多的依赖关系,这样当一个对象改变状态时,它的所有依赖者都会被通知并自动更新-GOF设计模式

观察者模式是一种非常常见的设计模式,该模式是 GOF 模式的行为设计模式系列的一部分,它解决了应用程序中对象的职责以及它们在运行时如何在它们之间进行通信。根据这种模式,有时对象会在应用程序中的对象之间建立一对多的关系,这样如果一个对象被修改,它会自动通知给 其他 依赖对象。

例如,Facebook 发表评论就是观察者设计模式的例子之一。如果您对朋友的帖子发表评论,那么每当其他人再次对同一帖子发表评论时,您都会收到该帖子的通知。

观察者模式提供解耦对象之间的通信。它使对象之间的关系主要是一对多的关系。在这种模式中,有一个称为主体的对象。每当此主题的状态发生任何变化时,都会相应地通知其家属名单。此受抚养人列表称为观察者。下图说明了观察者模式:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

观察者设计模式的用例

 

下面列出了使用观察者模式的好处:

  • This pattern provides decoupled relationship between the subject and observer
  • It provides support for broadcasting

让我们看看下面的 UML 图显示了观察者设计模式的所有组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

观察者设计模式的 UML 图

  • Subject: It is an interface. It has information about its observers.
  • ConcreteSubject: It is a concrete implementation of Subject, it has information about all its observers to be notified when its state changes.
  • Observer: It is an interface to be notified of changes in a subject.
  • ConcreteObserver: It is a concrete implementation of Observer, it keeps its state consistent with the subject's state.

Spring Framework 中的观察者模式

在 Spring Framework 中,观察者 design 模式用于实现 ApplicationContext 的事件处理功能。 Spring 为我们提供了 ApplicationEvent 类和 ApplicationListener 接口,以便在 Spring ApplicationContext 。 Spring 应用程序中的任何 bean 都实现了 ApplicationListener 接口,每次 ApplicationEvent >ApplicationEvent 由事件发布者发布。这里,事件发布者是主体,实现 ApplicationListener 的 bean 是观察者。

现在我们已经了解了观察者设计模式,让我们转向它的另一个变体——模板设计模式。

模板设计模式

在操作中定义算法的骨架,将一些步骤推迟到子类。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。 60; -GOF 设计模式

在模板 design 模式中,抽象类将一些已定义的方法包装到其方法中。该方法允许您覆盖方法的某些部分而不重写它。您可以在您的应用程序中使用它的具体类来执行类似类型的操作。这种设计模式属于 GOF 模式的行为设计模式家族。

下面列出了使用模板模式的好处

  • It reduces the boilerplate codes in the application by reusing code.
  • This pattern creates a template or way to reuse multiple similar algorithms to perform some business requirements.

让我们看看下面的 UML 图显示了模板设计模式的组件:

读书笔记《spring-5-design-patterns》第 3 章考虑结构和行为模式

模板设计模式的 UML 图

  • AbstractClass: This is an abstract class that contains a template method defining the skeleton of an algorithm.
  • ConcreteClass: This is a concrete subclass of AbstractClass that implements the operations to carry out the algorithm-specific primitive steps.

让我们看看下一部分关于企业分布式应用程序中的 J2EE 设计模式

JEE 设计模式


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

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

这些设计模式特别关注以下列出的层。

  • Design pattern at presentation layer:
    • View Helper: It separates views from the business logic of an enterprise J2EE application.
    • Front Controller: It provides a single point of action to handle the all coming requests to the J2EE web application, it forwards the request to specific application controller to access model and view for presentation tier resources.
    • Application Controller-The request actually handled by the Application Controller, it acts as a front controller helper. It responsible for the coordination with the business models and view components.
    • Dispatcher View-It is related to the view only and it executes without business logic to prepare a response to the next view.
    • Intercepting filters -In the J2EE web application, you could configure multiple interceptors for pre and post processing an user's request such as tracking and auditing user's requests.
  • Design pattern at business layer:
    • Business Delegate-It acts as a bridge between application controllers and business logic
    • Application Service-It provides business logics to implement the model as simple Java objects for presentation layer
  • Design pattern at integration layer:
    • Data Access Object-It is implemented for accessing business data and it separates data access logic from business logic in the enterprise application.
    • Web Service Broker-It encapsulates the logic to access the external application's resources and it is exposed as web services.

概括


阅读本章后,读者现在应该对 GOF 设计模式及其最佳实践有了一个很好的了解。我强调了如果您不在企业应用程序中实现设计模式会出现的问题,以及 Spring 如何通过使用大量设计模式和良好实践来创建应用程序来解决这些问题。在前面的章节中,我也提到了 GOF 设计模式的三个主要类别,例如创建设计模式;它对于创建对象实例很有用,并且还可以通过工厂、抽象工厂、构建器、原型和单例模式以特定方式在企业应用程序的创建时应用一些约束。第二个主要类别是结构设计模式,它用于通过处理类或对象的组合来设计企业应用程序的结构,从而降低应用程序的复杂性,提高应用程序的可重用性和性能。它们是适配器模式、桥接模式、复合模式、装饰器模式和外观模式属于这一类模式。最后,该模式的另一个主要类别是行为设计​​模式,它描述了类或对象交互和分配责任的方式。属于这一类的模式特别关注对象之间的通信。