面向对象设计模式

news/2024/9/19 6:28:19/ 标签: 设计模式, java, 单例模式

设计模式通常被分为三种类型:创建型模式、结构型模式和行为型模式。

创建型模式

创建型模式主要关注对象的创建机制,它们提供了一种将对象创建和实例化的机制,使得系统在不直接依赖于具体类的情况下能够灵活地创建对象。

创建型模式的典型代表包括工厂模式、抽象工厂模式、建造者模式、原型模式和单例模式

单例模式

java">public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

工厂模式

java">interface Shape {void draw();
}class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a rectangle");}
}class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a circle");}
}class ShapeFactory {public static Shape getShape(String type) {if (type.equalsIgnoreCase("rectangle")) {return new Rectangle();} else if (type.equalsIgnoreCase("circle")) {return new Circle();}return null;}
}

结构型模式

结构型模式主要关注对象的组合和结构,它们描述了如何将类或对象按照某种方式组合成更大的结构,以满足系统的需求。

结构型模式的典型代表包括适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式和代理模式。

装饰者模式

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地将责任附加到对象上,同时不改变其接口。装饰者模式通过创建装饰者类,用来包装原始类的对象,并向其添加新的行为或责任,从而实现了对对象功能的动态扩展。

装饰者模式通常涉及以下几种角色:

  1. Component(组件):组件是一个接口或抽象类,定义了被装饰者和装饰者共同的接口。它可以是一个抽象类,也可以是一个接口,用于定义被装饰者和装饰者共同的行为。

  2. ConcreteComponent(具体组件):具体组件是实现了组件接口的具体类,它是被装饰者,负责提供基本的功能。

  3. Decorator(装饰者):装饰者是一个抽象类,它实现了组件接口,并持有一个指向组件的引用。装饰者通常包含一个组件对象,用来装饰或包装真实的组件对象。

  4. ConcreteDecorator(具体装饰者):具体装饰者是实现了装饰者接口的具体类,它负责向组件添加新的行为或责任。

装饰者模式的核心思想是通过嵌套具体装饰者对象来动态地扩展对象的功能,而不是通过继承来实现。这样可以避免继承导致的类爆炸问题,并且使得每个类的职责更加清晰,更易于维护和扩展。

下面是一个简单的装饰者模式的示例代码:

java">// 组件接口
interface Coffee {String getDescription();double getCost();
}// 具体组件
class Espresso implements Coffee {@Overridepublic String getDescription() {return "Espresso";}@Overridepublic double getCost() {return 1.99;}
}// 装饰者抽象类
abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee decoratedCoffee) {this.decoratedCoffee = decoratedCoffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double getCost() {return decoratedCoffee.getCost();}
}// 具体装饰者
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}@Overridepublic double getCost() {return super.getCost() + 0.5;}
}class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Sugar";}@Overridepublic double getCost() {return super.getCost() + 0.2;}
}// 测试类
public class Test{public static void main(String[] args) {Coffee espresso = new Espresso();System.out.println("Description: " + espresso.getDescription());System.out.println("Cost: $" + espresso.getCost());Coffee milkCoffee = new MilkDecorator(espresso);System.out.println("Description: " + milkCoffee.getDescription());System.out.println("Cost: $" + milkCoffee.getCost());Coffee sugarMilkCoffee = new SugarDecorator(milkCoffee);System.out.println("Description: " + sugarMilkCoffee.getDescription());System.out.println("Cost: $" + sugarMilkCoffee.getCost());}
}

行为型模式

行为型模式主要关注对象之间的通信和交互,它们描述了对象之间的相互作用和协作方式,以实现系统中的功能。

行为型模式的典型代表包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

观察者模式

观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象的状态发生变化时,所有依赖于它的观察者都会得到通知并自动更新。

这种模式主要涉及两种角色:

  1. Subject(主题):也称为被观察者或可观察对象,它是一个具体类,负责维护一组观察者对象,并提供注册和删除观察者的接口,以及通知观察者的方法。

  2. Observer(观察者):也称为订阅者或监听者,它是一个接口或抽象类,定义了一个更新的接口,以便在主题状态变化时接收通知。

观察者模式的优点包括:

  • 松耦合:主题和观察者之间是松耦合的,主题只知道观察者实现了特定接口,而不需要了解其具体实现。
  • 可重用性:可以在同一主题上添加或移除不同的观察者对象,而无需修改主题代码。
  • 扩展性:可以轻松添加新的观察者以应对主题状态变化。

观察者模式的典型应用场景包括:

  • GUI(图形用户界面)程序中的事件处理:例如按钮点击事件、鼠标移动事件等。
  • 被观察者对象的状态变化需要通知多个观察者对象进行更新的情况。

下面是一个简单的观察者模式的示例代码:

java">import java.util.ArrayList;
import java.util.List;interface Observer {void update(String message);
}class Subject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer observer) {observers.add(observer);}public void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}
}class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received message: " + message);}
}// 测试类
public class Test{public static void main(String[] args) {// 创建一个主题对象Subject subject = new Subject();// 创建两个观察者对象Observer observer1 = new ConcreteObserver("Observer 1");Observer observer2 = new ConcreteObserver("Observer 2");// 注册观察者subject.addObserver(observer1);subject.addObserver(observer2);// 主题对象状态发生变化,通知观察者subject.notifyObservers("Hello, observers!");}
}

策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法(策略),并将每个算法封装到具有公共接口的独立类中,使得它们可以相互替换。策略模式使得算法可以独立于使用它们的客户端而变化,从而使得算法可以根据需要动态地切换、选择或替换。

策略模式主要涉及三种角色:

  1. Context(上下文):上下文是客户端使用策略的入口,它持有一个策略对象,并在需要的时候调用策略对象的方法。上下文类通常会将请求委派给策略对象来执行具体的算法。

  2. Strategy(策略):策略是一个接口或抽象类,它定义了一个算法族的共同接口。具体的策略类实现了这个接口,并实现了具体的算法。

  3. ConcreteStrategy(具体策略):具体策略类实现了策略接口,并提供了具体的算法实现。每个具体策略类都代表了一个具体的算法,客户端可以根据需求选择不同的具体策略来执行相应的算法。

策略模式的优点包括:

  • 可扩展性:新的策略可以很容易地添加到系统中,而不会影响现有的代码。
  • 可维护性:每个具体策略类都相对独立,易于维护和修改。
  • 松耦合:上下文类与具体策略类之间的耦合度较低,可以相互独立地变化。

下面是一个简单的策略模式的示例代码:

java">// 策略接口
interface Strategy {void execute();
}// 具体策略A
class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("Executing strategy A");}
}// 具体策略B
class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("Executing strategy B");}
}// 上下文类
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {strategy.execute();}
}// 测试类
public class Test{public static void main(String[] args) {// 创建具体策略对象Strategy strategyA = new ConcreteStrategyA();Strategy strategyB = new ConcreteStrategyB();// 创建上下文对象,并设置具体策略Context context = new Context(strategyA);// 执行具体策略context.executeStrategy();// 切换策略context.setStrategy(strategyB);context.executeStrategy();}
}

应用场景如,多种方式付款:

java">interface PaymentStrategy {void pay(int amount);
}class CreditCardStrategy implements PaymentStrategy {private String cardNumber;private String cvv;private String expirationDate;public CreditCardStrategy(String cardNumber, String cvv, String expirationDate) {this.cardNumber = cardNumber;this.cvv = cvv;this.expirationDate = expirationDate;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using credit card.");}
}class ShoppingCart {private PaymentStrategy paymentStrategy;public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void checkout(int amount) {paymentStrategy.pay(amount);}
}

http://www.ppmy.cn/news/1433509.html

相关文章

力扣---填充每个节点的下一个右侧节点指针 II

给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL 。 初始状态下&#xff0c;所有 next 指针都…

Prompt Engineering,提示工程

什么是提示工程&#xff1f; 提示工程也叫【指令工程】。 Prompt发送给大模型的指令。比如[讲个笑话]、[用Python编个贪吃蛇游戏]、[给男/女朋友写情书]等看起来简单&#xff0c;但上手简单精通难 [Propmpt]是AGI时代的[编程语言][Propmpt]是AGI时代的[软件工程][提示工程]是…

Spring5深入浅出篇:JDK代理与CGLIB代理区别

Spring5深入浅出篇:JDK代理与CGLIB代理区别 很多粉丝私信我这个Spring5的课程在哪看,这边是在B站免费观看欢迎大家投币支持一下. https://www.bilibili.com/video/BV1hK411Y7zf JDK动态代理与CGLIB的区别 在Java的世界里&#xff0c;动态代理主要有两种实现方式&#xff1a;JDK…

广州大学《虚拟现实与游戏开发》实验报告一HTC-VR环境搭建与开发

广州大学学生实验报告 开课实验室&#xff1a; 学院 年级、专业、班 姓名 学号 实验课程名称 虚拟现实与游戏开发 成绩 实验项目名称 1. HTC-VR环境搭建与开发 指导老师 实验目的 HTC VIVE硬件安装虚拟现实开发环境搭建 3.熟悉虚拟现实硬件系统和…

springboot-异步、定时、邮件任务

目录 一&#xff0c;前言 二&#xff0c;异步 2.1&#xff0c;案例&#xff1a; 1&#xff0c;首先创建一个service&#xff1a; 2&#xff0c;Controller: ① 想办法告诉spring我们的异步方法是异步的&#xff0c;所以要在方法上添加注解 Async ②去springboot主程序中开…

深入Spring Boot配置机制:如何高效管理应用配置

一、属性的优先级和配置文件的位置 在Spring Boot应用中&#xff0c;我们可以在多个地方定义配置属性&#xff0c;并且Spring Boot提供了一套优先级排序&#xff0c;来决定同一属性多处定义时的覆盖关系。理解这个机制对于配置管理至关重要。 1. 配置文件查找的顺序 Spring …

【debug记录】有gpu,但是 pytorch仍显示 cpu【原来是新电脑没安装cuda】

原来是新电脑没安装cuda&#xff0c;以为安装了pytorch包就可以了。 检查过程&#xff1a; nvcc 不是内部或外部命令&#xff0c;也不是可运行的程序, 说明没有安装cuda。 查看电脑显卡最高支持cuda版本&#xff1a;nvidia-smi 安装cuda&#xff0c;选择版本&#xff1a;ht…

基于小程序实现的查寝打卡系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

flink1.18.0 流转表 表转流 jdk17 attachAsDataStream

目的 流表互转 而且流sink 表sink同时存在且都可以输出. 依赖类 package flink.luca.flinkTableAndSQL.Convert;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class Outer…

gcc/g++ 的使用

————gcc&#xff1a;只能编译c语言 ————g&#xff1a;c和c都可以编译 当然&#xff0c;c语言编译还是推荐gcc。 在学习gcc/g之前&#xff0c;我们要先了解一些知识点&#xff1a; 一、背景知识 1&#xff0c;预处理 gcc -E就是告诉编译器到预处理阶段就停下来&am…

QBoxLayout的addWidget(QWidget * w)会改变w的parent()

示例&#xff1a; 我希望在page_frame对象中使用orders_add_page对象的price变量&#xff0c; 但按照下面这样写得到的price的值都不对。 int price; orders_add_page::orders_add_page(QWidget *parent): QDialog(parent) {ui.setupUi(this);page new page_frame(type, t…

Windows10如何关闭Edge浏览器的Copilot

在Windows10更新后&#xff0c;打开Edge浏览器&#xff0c;无论复制什么内容&#xff0c;都会弹出Copilot人工智能插件&#xff0c;非常令人反感&#xff0c;网上搜索的关闭方法都非常麻烦&#xff0c;比如&#xff1a;组策略和注册表。自己摸索得出最简便有效的关闭方法。 1、…

go语言实现简单登陆样例

目录 1、代码实现样例&#xff1a; 2、postman调用&#xff0c;获取登陆后的token&#xff1a; 1、代码实现样例&#xff1a; package mainimport ("net/http""time""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin" )var …

【算法】约瑟夫环

文章目录 题目一1.数组模拟1.1出圈顺序递归求出圈顺序 1.2最后出圈人 2.环形链表【DEMO】3.递推求最后出圈人3.13.2 题目二1.数组模拟2.递推求最后出圈人2.12.2 题目一 1-n编号 s开始1-m报数 报到m出圈 求出圈顺序or最后人 1.数组模拟 1.1出圈顺序 递归求出圈顺序 // AC输入…

开源模型应用落地-LangChain高阶-集成vllm-QWen1.5(一)

一、前言 通过langchain框架调用本地模型,使得用户可以直接提出问题或发送指令,而无需担心具体的步骤或流程。vLLM是一个快速且易于使用的LLM推理和服务库。通过两者的结合,可以更好地处理对话,提供更智能、更准确的响应,从而提高对话系统的性能和用户体验。 二、术语 2.…

大语言模型微调过程中的 RLHF 和 RLAIF 有什么区别?

目前想要深入挖掘大型语言模型&#xff08;LLM&#xff09;的全部潜力需要模型与我们人类的目标和偏好保持一致。从而出现了两种方法&#xff1a;来自人类反馈的人力强化学习&#xff08;RLHF&#xff09;和来自人工智能反馈的人工智能驱动的强化学习&#xff08;RLAIF&#xf…

服务器基础知识(2)

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;服务器❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 一、如何选择服务器主机 选择服务器主机时&#xff0c;需要考虑以下几个关键因素&#xff1a; 用途和需…

MYSQL 8.0的Linux - Generic版本安装

1.本文适用范围 适用于MYSQL 8.0的Linux - Generic版本&#xff0c;原则上适用所有的操作系统。已测试的操作系统包括&#xff1a; Ubuntu 16.04Ubuntu 18.04Ubuntu 20.04Ubuntu 22.04Kylin Linux Advanced Server V10 ​ 注意&#xff1a;如果操作系统使用过包管理系统&…

JAVA toString方法详解

hi&#xff0c;我是程序员王也&#xff0c;一个资深Java开发工程师&#xff0c;平时十分热衷于技术副业变现和各种搞钱项目的程序员~&#xff0c;如果你也是&#xff0c;可以一起交流交流。 今天我们来聊聊Java中toString方法~ toString方法的定义 在Java中&#xff0c;toStri…

医院信创FTP要进行替代,有什么值得信赖的方案?

信创产业&#xff0c;即信息技术应用创新产业。其发展核心在于通过行业 应用拉动构建国产化信息技术软硬件底层架构体系和全生命周期生态体系&#xff0c;解决核心技术关键环节“卡脖子”的问题&#xff0c;为中国未来发展奠定坚实的数字基础。 2018 年 以来&#xff0c;受“华…