Java设计模式:深入解析与应用示例 雨点打透心脏的1/2处 2024-03-16 18:59 41阅读 0赞 #### 文章目录 #### * 引言 * * 一、单例模式 * 二、工厂模式 * 三、抽象工厂模式 * 四、建造者模式 * 五、原型模式 * 六、适配器模式 * 七、装饰器模式 * 八、观察者模式 * 九、策略模式 * 十、命令模式 * * 结语 ## 引言 ## 设计模式是一种在特定上下文中反复出现的可重用解决方案,用于处理软件设计中常见的问题。掌握设计模式不仅可以帮助我们编写出更优雅、更易于理解和维护的代码,而且也是Java面试中的常考知识点。在本文中,我们将探讨几种常见的设计模式,包括它们的定义、使用场景和Java实现。 ### 一、单例模式 ### 单例模式确保一个类只有一个实例,并提供全局访问点。这种设计模式属于创建型模式,它涉及一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 应用场景:需要频繁实例化然后销毁的对象,数据库连接、线程池等长时间存在于系统中的对象。 **示例代码:** public class Singleton { // 使用volatile关键字防止指令重排序 private static volatile Singleton instance; private Singleton() { } // 提供全局访问点 public static Singleton getInstance() { // 第一次检查 if (instance == null) { // 加锁 synchronized (Singleton.class) { // 第二次检查 if (instance == null) { instance = new Singleton(); } } } return instance; } } 我们创建了一个 `Singleton` 类。`Singleton` 类有一个 `getInstance()` 方法,它可以返回 `Singleton` 类的一个实例。在这个类中,我们有一个私有构造函数,它可以防止其他类实例化这个类。而 `getInstance()` 方法可以为其他类提供了一种方式来获取这个类的单一实例。 ### 二、工厂模式 ### 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 应用场景:在编码时不能预见需要创建哪种类的实例,系统需要提供一个接口,让系统与其各种具体实现类之间解耦。 **示例代码:** public interface Shape { void draw(); } public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } } public class ShapeFactory { // 使用getShape方法获取形状类型的对象 public Shape getShape(String shapeType) { if (shapeType.equalsIgnoreCase("RECTANGLE")) { return new Rectangle(); } // other shape types... return null; } } 我们首先创建了一个接口 `Shape` 和实现了 `Shape` 接口的实体类。然后我们创建了一个工厂类 `ShapeFactory`。`ShapeFactory` 类有一个方法 `getShape` ,根据输入的类型,返回一个实体类的实例。在这个例子中,我们的工厂类 `ShapeFactory` 是如何根据我们提供的信息来返回不同类的实例的。 ### 三、抽象工厂模式 ### 抽象工厂模式是一种创建型设计模式,它提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在抽象工厂模式中,抽象工厂定义了产品是什么,为创建一系列相关或相互依赖的对象提供一个接口,而无需指定它们具体的类。 应用场景:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。 **示例代码:** public interface GUIFactory { Button createButton(); Checkbox createCheckbox(); } public class WinFactory implements GUIFactory { // 返回WinButton类的实例 public Button createButton() { return new WinButton(); } // 返回WinCheckbox类的实例 public Checkbox createCheckbox() { return new WinCheckbox(); } } 和工厂模式类似,但是这次我们添加了一个新的层次——工厂创造器/生成器类 `FactoryProducer`。`AbstractFactory` 类是所有工厂类的超类,`FactoryProducer` 可以根据传入的信息返回一个特定的工厂。 ### 四、建造者模式 ### 建造者模式是一种创建型设计模式,它可以将一个复杂对象的建造过程抽象出来(抽象为指挥者和建造者),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的复杂对象。具体来说,将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 应用场景:需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个部分。 **示例代码:** public class Pizza { private String dough = ""; private String sauce = ""; private String topping = ""; // setters... } public class PizzaBuilder { private Pizza pizza; public PizzaBuilder() { pizza = new Pizza(); } public PizzaBuilder setDough(String dough) { pizza.setDough(dough); return this; } public PizzaBuilder setSauce(String sauce) { pizza.setSauce(sauce); return this; } public PizzaBuilder setTopping(String topping) { pizza.setTopping(topping); return this; } // 最终构建复杂的Pizza对象并返回 public Pizza build() { return pizza; } } `Packing` 和 `Item` 接口表示食物和食物包装。然后我们有了实体类实现了这些接口,`Burger` 和 `ColdDrink` 实现了 `Item` 接口,`Wrapper` 和 `Bottle` 实现了 `Packing` 接口。`Meal` 类是一个组合类,包含了 `Item` 对象。`MealBuilder` 是实际的构建器,负责创建 `Meal` 对象。 ### 五、原型模式 ### 原型模式是创建型设计模式,通过复制一个已存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。 应用场景:创建对象成本较大(如初始化需要消耗很多时间,占用太多CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。 **示例代码:** public class Prototype implements Cloneable { // 使用 clone() 方法来创建新的实例 public Prototype clone() { try { return (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } } 在原型模式中,我们通过复制一个已存在的对象来创建新的对象。我们创建了一个抽象类 `Shape` 和几个扩展了 `Shape` 类的实体类。`ShapeCache` 类是一个缓存类,将shape对象存储在一个 Hashtable 中,并在请求的时候返回它们的克隆。 ### 六、适配器模式 ### 适配器模式是一种结构型设计模式,它通过把一个类的接口变换成客户端所期待的另一种接口,可以帮助我们解决不兼容的问题。这个模式主要应用于希望复用那些与新系统不兼容的旧组件的场景,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。 应用场景:已经存在的类,它的方法和我们的需求不一样,也就是接口不相同,或者我们创建了一个可复用的类,该类可能和现有的类库不是很兼容,需要在双方都不易修改的情况下使用适配器模式。 **示例代码:** // 目标接口,或称为标准接口 public interface MediaPlayer { void play(String audioType, String fileName); } // 适配器类,实现MediaPlayer接口 public class MediaAdapter implements MediaPlayer { // 适配器中包含了一个需要适配的对象 AdvancedMediaPlayer advancedMusicPlayer; public MediaAdapter(String audioType) { if (audioType.equalsIgnoreCase("vlc")) { advancedMusicPlayer = new VlcPlayer(); } else if (audioType.equalsIgnoreCase("mp4")) { advancedMusicPlayer = new Mp4Player(); } } // 调用适配器中的方法 public void play(String audioType, String fileName) { if (audioType.equalsIgnoreCase("vlc")) { advancedMusicPlayer.playVlc(fileName); } else if (audioType.equalsIgnoreCase("mp4")) { advancedMusicPlayer.playMp4(fileName); } } } 我们有一个 `MediaPlayer` 接口和一个实现了 `MediaPlayer` 接口的实体类。然后我们创建了另一个接口 `AdvancedMediaPlayer` 和实现了 `AdvancedMediaPlayer` 接口的实体类。然后我们创建了一个适配器类 `MediaAdapter`,它使用 `AdvancedMediaPlayer` 对象来播放所需要的格式。 ### 七、装饰器模式 ### 装饰器模式是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它在不需要使用继承的情况下为对象动态添加新的功能。 应用场景:在不想增加很多子类的情况下扩展类,需要动态增加及撤销对象的功能。 **示例代码:** // 定义接口Shape public interface Shape { void draw(); } // 定义装饰器DecoratorShape public class DecoratorShape implements Shape { protected Shape decoratedShape; public DecoratorShape(Shape decoratedShape) { this.decoratedShape = decoratedShape; } // 在装饰器中调用原始对象的方法,并添加新的功能 public void draw() { decoratedShape.draw(); System.out.println("Additional decoration function."); } } 我们有一个 `Shape` 接口和实现了 `Shape` 接口的实体类。然后我们创建了一个抽象的装饰器类 `ShapeDecorator`,并扩展了 `Shape` 接口,此装饰器类在被装饰类上进行了一层包装,以增加新的功能。 ### 八、观察者模式 ### 观察者模式是一种行为型设计模式,定义对象间的一种一对多的依赖关系,使得当一个对象的状态发生改变时,其相关依赖对象皆会得到通知并被自动更新。观察者模式属于行为型模式。 应用场景:当一个对象的改变需要同时改变其他对象,并且它不知道具体有多少对象需要改变,就可以考虑使用观察者模式。 **示例代码:** // 定义Subject,持有观察者的列表,并提供attach和notifyAllObservers方法 public class Subject { private List<Observer> observers = new ArrayList<Observer>(); public void attach(Observer observer) { observers.add(observer); } public void notifyAllObservers() { for (Observer observer : observers) { observer.update(); } } } // 定义Observer,声明更新自己的抽象方法 public abstract class Observer { protected Subject subject; public abstract void update(); } 我们创建了 `Subject` 类、`Observer` 抽象类和扩展了 `Observer` 类的实体类。`Subject` 对象改变状态时,所有依赖于它的对象都会得到通知,并自动更新。 ### 九、策略模式 ### 策略模式是一种行为型设计模式,它定义了一系列的算法,并将每一个算法封装起来,而且使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。 应用场景:一个系统有很多类的算法或者业务逻辑,可以把这些算法或者业务逻辑封装在同一个接口的不同的实现类中,减少使用多重转移语句(if…else if…else)。 **示例代码:** // 定义策略接口,声明算法方法 public interface Strategy { public int doOperation(int num1, int num2); } // 定义具体策略类 public class OperationAdd implements Strategy { public int doOperation(int num1, int num2) { return num1 + num2; } } // 环境类,持有一个策略类的引用 public class StrategyContext { private Strategy strategy; public StrategyContext(Strategy strategy) { this.strategy = strategy; } // 使用策略的方法 public int executeStrategy(int num1, int num2) { return strategy.doOperation(num1, num2); } } 我们定义了一个策略接口 `Strategy` 和实现了 `Strategy` 接口的实体策略类。`Context` 是一个使用了某种策略的类。`Context` 对象使用了一些策略对象,这个策略对象改变了 `Context` 对象的执行算法。 ### 十、命令模式 ### 命令模式是一种行为型设计模式,它通过在对象之间引入级别,使得对象之间的依赖关系变得更加简单,并且降低了组合和调用的复杂性。这种模式涉及到五个组件:Client、Invoker、Command、ConcreteCommand、Receiver。 应用场景:当需要为请求调用者与请求接收者解耦时,命令模式使得调用者与接收者不直接交互,并且调用者无需知道接收者的接口。命令模式可以用于有多个触发者或接收者,需要向多个对象发出请求。 **示例代码:** // 命令接口,声明执行方法 public interface Order { void execute(); } // 具体命令类,实现Order接口的execute方法,调用接收者的方法 public class StockRequest implements Order { private Stock stock; public StockRequest(Stock stock) { this.stock = stock; } public void execute() { stock.buy(); } } // 调用者类,接收命令并执行 public class Broker { private List<Order> orderList = new ArrayList<Order>(); public void takeOrder(Order order) { orderList.add(order); } public void placeOrders() { for (Order order : orderList) { order.execute(); } orderList.clear(); } } 我们创建了一个请求类 `Stock`,一个命令接口 `Order` 和实现了 `Order` 接口的实体命令类。命令实现类持有一个对请求的引用,并执行这个请求。`Broker` 对象使用命令对象和队列来执行请求。 #### 结语 #### 在这篇博客中,我们研究了10种常用的Java设计模式,希望这些知识能帮助你在日常开发或面试中更好地解决问题。记住,设计模式只是工具。在实际项目中,我们应该根据项目需求和具体情况选择合适的设计模式,而不是强行套用。
相关 Java反射机制深入解析:实用示例与应用场景 Java的反射机制是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息。以下是深入解析反射机制的几个方面: 1. **什么是反射?** 反射是Java语言中的一 悠悠/ 2024年09月19日 13:30/ 0 赞/ 15 阅读
相关 Java反射机制深入解析与应用实例 Java反射机制是一种强大的工具,它允许我们在运行时检查类、字段和方法等信息。以下是对反射机制的深入解析以及应用实例: 1. **获取类信息**: - `Class<T 拼搏现实的明天。/ 2024年09月16日 03:57/ 0 赞/ 23 阅读
相关 Java设计模式:单例模式的应用示例 单例模式是一种常用的对象创建设计模式,主要目的是保证一个类只有一个实例,并提供一个全局访问点。 以下是一个简单的Java单例模式应用示例: ```java // 单例类的定 旧城等待,/ 2024年09月15日 06:51/ 0 赞/ 20 阅读
相关 设计模式实践:Java Singleton模式应用示例 Singleton模式是设计模式中的一个,它保证了一个类只有一个实例,并提供一个全局访问点。 以下是Java中实现Singleton模式的一个简单示例: ```java / 不念不忘少年蓝@/ 2024年09月11日 23:54/ 0 赞/ 16 阅读
相关 Java设计模式:深入解析与应用示例 文章目录 引言 一、单例模式 二、工厂模式 三、抽象工厂模式 四、建造者模式 五、原型模式 雨点打透心脏的1/2处/ 2024年03月16日 18:59/ 0 赞/ 42 阅读
相关 【设计模式】深入解析建造者模式 目录 一、前言 二、建造者模式定义 三、建造者模式的结构 四、应用 五、示例代码 六、主要解决 七、建造者模式的优缺点 1、优点 2、缺点 八、总结 - 清疚/ 2023年10月11日 17:19/ 0 赞/ 11 阅读
相关 PHP设计模式|观察者模式(Observer)解析与应用 【观察者模式结构图】 ![format_png][] 概念 (Observer),首先要有一个被观察的角色,但ta是【唯一的】。虽然"表演者"只有一个但是"观众"有很 傷城~/ 2022年11月29日 03:05/ 0 赞/ 42 阅读
相关 PHP设计模式|观察者模式(Observer)解析与应用 使用场景 假设项目经理让我们写了一个登陆接口,咔咔擦擦写完了 第二天让我们加入统计登陆次数,然后在后面加代码 第三天让我们判断登陆地区,又在后面加代码 朴灿烈づ我的快乐病毒、/ 2022年11月29日 03:05/ 0 赞/ 38 阅读
相关 深入解析单例设计模式 文章目录 1.单例设计模式 1.1 单例设计模式的定义: 1.2单例设计模式的要点有三个: 1 不念不忘少年蓝@/ 2022年04月12日 07:56/ 0 赞/ 179 阅读
还没有评论,来说两句吧...