Java中24种常用设计模式的基本原理介绍为什么需要设计模式,在哪里使用设计模式。本文是Java设计模式系列技术文章的开篇。作为入门文章,快速解读设计模式的基本概念、模式分类和适用范围。在后面的章节中,将对每一种设计模式进行详细的讲解,讲解的内容包括三个部分:每种设计模式的基本原理、适用范围、实战案例分析。1模式的基本概念模式是指解决特定领域中的问题并达到既定目标的方法或思想。具体来说,模型是某一行业的从业者根据实际工作经验总结出来的通用的、行业公认的解决问题的方法或流程。模式不仅应用于软件工程,还广泛应用于日常生产活动,如制造、餐饮、建筑设计、医疗保健、教育培训、软件工程等。2什么是设计模式?首先,设计模式是一种模式。在软件工程中,设计模式是一种通用的、可重用的软件设计方法,用于解决给定范围内经常发生的重复性问题。使用成熟可靠的设计模式可以提高代码的可重用性并节省开发时间,从而产生更强大和高度可维护的代码。这有助于降低软件产品的总拥有成本,即TCO(TotalCostofOwnership)。另一方面,由于采用了统一的标准设计方法(思想或理论知识),开发团队的生产力和协作能力可以显着提高。3Java设计模式的分类在Java编程语言中,常用的设计模式可以分为三种:构造类设计模式:主要用于定义和约束如何创建一个新的对象结构类设计模式:主要用于定义How使用多个对象组合一个或多个复合对象行为类设计模式:主要用于定义和描述对象之间的交互规则,限定对象的职责边界线图3-1设计模式分类3.1构造类设计模式构造类包括五(5)种基本设计模式:单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式,如图3-2所示:图3-2构造类设计模式3.2结构类设计模式结构类包括八(8)个基本设计模式:适配器模式、复合模式、代理模式、享元模式、过滤模式、桥接模式、装饰模式和外观模式,如图3-3所示:图3-3结构类设计模式3.3行为类设计模式行为类包括十一(11)种基本设计模式:模板方法模式、解释器模式、责任链模式、观察者模式、策略模式、命令模式、状态模式、访客模式、逃逸模式、迭代器模式和备忘录模式,如图3-4所示:图3-4行为设计模式设计模式不仅限于上面介绍的三类,除此之外还有很多其他的设计模式。已知的设计模式有100多种,例如DAO模式、依赖注入模式和MVC模式。4快速??理解设计模式在接下来的内容中,我们将快速梳理Java中24种常见设计模式的基本概念,以期对各种设计模式的原理和适用范围有一个大概的了解。4.1构造类构造类设计模式提供了创建对象的基本定义和约束,以寻求实例化Java对象的最佳方案。4.1.1单例模式-Singleton单例模式限制了一个类的实例化过程,保证一个类在Java虚拟机(JVM)中只有一个实例化对象。单例模式是Java中最常用也是最简单的设计模式之一。单例模式通常需要具备以下特点:单例模式限制了类的实例化,Java虚拟机中只能有一个该类的实例化对象。单例模式必须提供一个全局可用的访问入口来获得单例模式。单例模式通常用于日志记录、驱动程序对象设计、缓存和线程池。单例模式还用于其他设计模式,如抽象工厂模式、建造者模式、原型模式等。单例模式的Java类的内部结构如图4-1所示:图4-1单例模式类图下面是单例模式的示例代码清单:4.1.2工厂模式-Java编程中的Factory在处理过程中,当一个父类有多个子类,需要频繁创建子类对象时,我们可以使用工厂模式.工厂模式的作用是将子类的实例化交给工厂类。工厂类通过对输入参数的判断,自动实例化具体的子类。实现工厂模式需要满足三个条件:超类(superclass):超类是一个抽象类子类(subclass):子类需要继承超类工厂类(factoryclass):工厂类根据输入参数实例化子类图4-2是Java工厂模式的类图:图4-2工厂模式UML类图下面是工厂模式的示例代码清单:4.1.3摘要工厂模式-抽象工厂抽象工厂模式与工厂模式非常相似,同样,抽象工厂模式可以简单理解为“工厂的工厂”。在工厂模式下,根据提供的输入参数返回产品类的实例化对象。这个过程需要通过if-else或者switch等逻辑判断语句来完成对具体子类的判断。在抽象工厂模式中,每个产品都有一个具体的工厂类与之对应,从而避免了在编码过程中使用大量的逻辑判断代码。抽象工厂模式会根据输入的工厂类型返回一个具体的工厂子类。抽象工厂类只负责实例化工厂子类,不参与商品子类的实例化。图4-3是抽象工厂模式的UML类图:图4-3抽象工厂模式4.1.4建造者模式-建造者建造者模式通常用于需要多步创建对象的场景。建造者模式的主要意图是将类的构造逻辑转移到类的实例化中。当一个类有很多属性时,在实例化类的对象时,并不一定拥有实例化对象的所有属性信息,可以使用构建器模式,通过逐步获取类的属性信息来完成类的实例化过程实例化的对象。工厂模式和抽象工厂模式在实例化时需要获取该类实例化对象的所有属性信息。图4-4展示了建造者模式的基本逻辑关系:图4-4建造者模式UML类图4.1.5原型模式-Prototype原型模式的主要作用是通过复制(克隆)的方式来使用已有的类创建一个新对象。当实例化一个类的对象需要大量的时间和系统资源时,可以采用原型模式,通过对原有已有对象的复制(克隆)机制创建一个新的对象,然后根据需要修改新的对象。原型模式要求被复制的对象本身具有复制功能,这是外界无法完成的。图4-5展示了原型模式的基本逻辑:图4-5原型模式UML类图4.2结构类结构类设计模式主要解决如何将多个小对象组合成一个大对象的问题,例如使用继承和interfaces实现将多个类组合在一起。4.2.1Adapter模式-AdapterAdapter模式的主要作用是让多个已有的可用接口共同为客户端提供新的接口服务。在适配器模式中,负责连接不同接口的对象成为适配器。在现实生活中,我们也可以找到很多实际案例来了解适配器的工作原理,比如常用的手机充电头,在手机和电源插座之间,手机充电头充当一个适配器,这可同时适配220V、200V、120V等不同电压,最终将电能转换为手机可用的5V电压,为手机充电。图4-6展示了适配器的基本原理:图4-6适配器模式UML类图4.2.2复合模式-Composite复合模式的主要作用是使整体和部分具有之前相同的行为。比如我们要画一个图形(正方形、三角形、圆形或者其他多边形),首先需要准备一张白纸,然后选择绘制图案的颜色,然后确定绘制图案的大小,最后绘制图案。无论您是绘制正方形还是三角形,都需要遵循此步骤。在软件设计过程中,复合模式最大的意义在于保证客户端在调用单个对象和复合对象时,其操作过程是一致的。图4-7展示了组合模式的基本原理:图4-7组合模式UML类图4.2.3代理模式-Proxy代理模式的主要作用是通过提供一个代理对象或一个代理对象来控制实际对象。占位符访问行为。代理模式通常用于需要频繁操作一些复杂对象的地方。通过使用代理模式,目标对象可以被代理类操作,简化了操作过程。图4-8展示了代理模式的基本原理:图4-8代理模式UML类图4.2.4享元模式-Flywight享元模式的主要作用是有效支持大量的细粒度对象通过分享。例如,当你需要创建一个类的很多对象时,你可以使用享元模式,通过共享对象信息来减少内存负载。如果在软件设计过程中使用享元模式,需要考虑以下三个问题:应用程序是否需要创建大量的对象?对象创建对内存消耗和时间消耗有严格要求吗?物体的属性是否可以分为内在属性和外在属性?对象的外部属性是否支持客户端定义?图4-9展示了享元模式的基本原理:图4-9享元模式UML类图4.2.5外观模式-Facade外观模式的主要作用是为子系统中的一组接口提供一个统一的接口,以便客户端更容易使用子系统中的接口。简单的理解就是门面模式为很多复杂的接口定义了一个更高级的接口。外观模式的目的是让界面更易于使用。图4-10展示了外观模式的基本原理:图4-10外观模式的UML类图4.2.6桥接模式-Bridge桥接模式的主要目的是将抽象类转化为它与类分离抽象类的具体实现实现结构解耦,使抽象和实现可以独立变化。桥接模式的实现遵循组合而不是继承。使用桥接模式时,一定程度上可以在客户端内部实现。图4-11展示了桥接模式的基本原理:图4-11桥接模式UML类图4.2.7装饰模式-Decorator装饰模式的主要作用是在运行时动态组合类的行为。通常,您会添加一些新类或新方法来扩展现有代码库。但是,在某些情况下,您需要在程序运行时为对象组合新的行为。这时候就可以使用装修模式了。图4-12展示了装饰模式的基本原理:图4-12装饰模式的UML类图4.2.8过滤模式-Filter过滤模式使用不同的标准过滤一组对象,并通过逻辑运算将它们解耦组合对象的方式。图4-13展示了过滤模式的基本原理:图4-13过滤模式4.3行为类行为类设计模式主要用于定义和描述对象之间的交互规则和职责边界,更好的进行对象交互提供解决方案。4.3.1模板方法模式-TemplateMethod模板方法模式的主要作用是在方法中实现一个算法,将算法中的一些步骤抽象成方法,将这些方法的实现推迟到子类中。比如盖房子,要设计图纸、打地基、砌墙、装门窗、室内装修。我们可以设计不同的房屋风格(别墅、高层、板房等)、不同的门窗、不同的装修材料和风格,但顺序不能颠倒。在这种情况下,我们可以定义一个模板方法,指定方法的执行顺序,将方法的实现推迟到子类中。图4-14展示了模板方法模式的基本原理:图4-14模板方法模式的UML类图组对象的交互降低了对象的耦合度,避免了对象之间的显式引用,可以改变对象的行为对象独立。解释器(中介)模式可以在系统中的不同对象之间提供一个集中的交互媒介,降低系统中各个组件的耦合度。图4-15展示了解释器(中介)模式的基本原理:图4-15解释器(中介)模式UML类图4.3.3责任链模式-ChainofResponsibility责任链模式的主要作用是让多个objects有机会处理同一个任务(请求)来解耦请求的发送者和接收者。try-catch是责任链模式的典型应用案例。在try-catch语句中,可以同时存在多个catch语句块,每个catch语句块是一个处理特定异常的处理器。当try语句块出现异常时,异常会被送到第一个catch语句块处理,如果第一个语句块无法处理,则请求转发到链中的下一个catch语句块。如果最后一个catch语句块仍然无法处理异常,则向上抛出异常。图4-16展示了责任链模式的基本原理:图4-16责任链模式UML类图4.3.4观察者模式-Observer观察者模式的目的是定义多个之间的一对多依赖关系objects关系,当一个对象的状态发生变化时,观察者会通知依赖它的对象,并根据新的状态做出相应的反应。简单来说,如果需要在对象状态发生变化时得到及时通知,可以定义一个监听器来监听对象的状态。这时的监听者就是一个观察者(Observer),被监听的对象被称为主体(Subject)。Java消息服务(JMS)使用观察者设计模式(以及中介模式)来允许应用程序订阅数据并将数据发布到其他应用程序。图4-17展示了观察者模式的基本原理:图4-17观察者模式UML类图4.3.5策略模式-Strategy策略模式的主要目的是将可互换的方法封装在自己独立的类中,并具有每个方法实现一个共同的操作。策略模式定义了策略的输入输出,实现由各个独立的类完成。策略模式允许一组策略共存而不干扰彼此的代码。它不仅将选择策略的逻辑与策略本身分离,而且有助于我们组织和简化代码。一个典型的例子是Collections.sort()方法,它使用Comparator作为方法参数,对象将根据实现Comparator接口的类以不同的方式进行排序。图4-18展示了策略模式的基本原理:图4-18策略模式的UML类图4.3.6命令模式-Command命令模式的设计意图是将请求封装在对象内部。直接调用是一种常见的方法执行方式,但在某些情况下,我们无法控制方法执行的时机和上下文信息。在这种情况下,可以将方法封装在对象内部,通过在对象内部存储调用者所需的信息,客户端或服务可以自由决定何时调用该方法。命令模式的基本原理如图4-19所示:图4-19命令模式UML类图4.37状态模式-State状态模式的设计意图是对象的状态改变其行为。如果我们必须根据对象的状态改变对象的行为,可以在对象中定义一个状态变量,使用逻辑判断语句块(如if-else)根据状态进行不同的操作。图4-20展示了状态模式的基本原理:图4-20状态模式UML类图4.3.8访问者模式-Visitor访问者模式的设计意图是在不改变现有类层次结构的情况下对层次结构进行分类。结构得到扩展。例如,在一个购物网站中,我们将不同的商品添加到购物车中,然后当支付按钮被按下时,它会计算出需要支付的总金额。我们可以在购物车类中完成金额的计算,或者使用访问者模式将购物应付金额的逻辑转移到一个新的类中。图4-21展示了访问者模式的基本原理:图4-21访问者模式UML类图4.3.9转义(翻译)模式-解释器转义(翻译)模式的设计意图是让你的一组组合组成可执行对象的规则。实现转义(翻译)模式的一个基本步骤如下:创建执行解释的上下文。引擎根据不同的表达式实现类,以实现上下文中的解释。创建一个从用户那里获取输入并决定使用哪个表达式输出转义内容的客户端图4-22显示了转义(翻译)模式的基本原理:图4-22转义(翻译)模式UML类图4.3。10迭代器模式——迭代器迭代器模式提供了一种迭代一组对象的标准方法。迭代器模式在JavaCollection框架中被广泛使用,Iterator接口提供了遍历集合元素的方法。迭代器模式不仅仅是为了遍历集合,我们还可以根据不同的需求提供不同类型的迭代器。迭代器模式通过集合隐藏了内部的遍历细节,客户端只需要使用相应的迭代方法即可完成元素遍历操作。图4-23展示了迭代器的基本原理:图4-23迭代器模式UML类图4.3.11备忘录模式-Memento备忘录模式的设计意图是为对象的状态提供存储和恢复功能。Memento模式由两个对象实现-Originator和Caretaker。Originator需要有保存和恢复对象状态的能力,它使用一个内部类来保存对象的状态。内部之所以称为备忘录,是因为它是对象私有的,所以外部类不能直接访问它。图4-24显示了备忘录模式的基本原理:图4-24备忘录模式的UML类图部分模式是一种通用的、可重用的软件设计方法,用于解决给定范围内常见的、反复出现的问题。同时,对Java中常见的设计模式进行了分类。设计模式分为构造型、结构型和行为型三种,并介绍了每一类设计模式的基本概念和原则。在后面的章节中,详细介绍了各个设计模式的原理、用法和适用范围,并给出了相应的实战源码。
