GDPU Java 天码行空6

一、实验目的

1、理解设计模式的基本思想;
2、理解并掌握常用的几种设计模式;
3、根据需求编写简单工厂设计模式;
4、根据需求编写适配器设计模式;

二、实验内容和步骤

1. 简单工厂模式实现计算器

请用简单工厂模式设计并编码实现一个计算器。工厂类根据键盘输入产生加、减、乘、除运算对象,并输出运算结果。贴出代码及运行截图

💖 SimpleFactoryDemo.java

import java.util.Scanner;public class SimpleFactoryDemo
{public static void main(String[] args){CalculatorSimpleFactory factory = new CalculatorSimpleFactory();//		测试Scanner sc = new Scanner(System.in);while (true){menu();int a = 0, b = 0;String type = null;try{a = sc.nextInt();type = sc.next();b = sc.nextInt();Calculator calculator = CalculatorSimpleFactory.getCalculator(type, a, b);double ans = calculator.calculate();System.out.println(ans);} catch (Exception e){String msg = e.getMessage();sc = new Scanner(System.in);if (msg != null)System.err.println(msg);elseSystem.err.println("输入格式有误,请重新输入!!");continue;}}}private static void menu(){System.out.println("请按格式输入: 【操作数1 运算符 操作数2】中间空格隔开");}
}class CalculatorSimpleFactory
{/*** 根据计算类型和操作数创建相应的计算器对象* * @param calculateType 计算类型,如"+", "-", "*", "/"* @param operator1     第一个操作数* @param operator2     第二个操作数* @return 对应的计算器对象*/public static Calculator getCalculator(String calculateType, double operator1, double operator2){Calculator calculator = null;switch (calculateType){case "+":case "加":calculator = new AddCalculator(operator1, operator2);break;case "-":case "减":calculator = new SubtractCalculator(operator1, operator2);break;case "*":case "×":case "乘":calculator = new MultiplyCalculator(operator1, operator2);break;case "/":case "÷":case "除":calculator = new DivideCalculator(operator1, operator2);break;default:throw new RuntimeException("暂不支持此计算功能!");}return calculator;}
}/*** 计算器抽象类,定义了计算器的基本属性和方法*/
abstract class Calculator
{double operator1;double operator2;public Calculator(double operator1, double operator2){super();this.operator1 = operator1;this.operator2 = operator2;}/*** 抽象方法,用于计算具体的运算结果* * @return 运算结果*/public abstract double calculate();
}/*** 加法计算器类,继承自计算器抽象类,实现了加法运算*/
class AddCalculator extends Calculator
{public AddCalculator(double operator1, double operator2){super(operator1, operator2);}@Overridepublic double calculate(){return super.operator1 + super.operator2;}
}/*** 减法计算器类,继承自计算器抽象类,实现了减法运算*/
class SubtractCalculator extends Calculator
{public SubtractCalculator(double operator1, double operator2){super(operator1, operator2);}@Overridepublic double calculate(){return super.operator1 - super.operator2;}
}/*** 乘法计算器类,继承自计算器抽象类,实现了乘法运算*/
class MultiplyCalculator extends Calculator
{public MultiplyCalculator(double operator1, double operator2){super(operator1, operator2);}@Overridepublic double calculate(){return super.operator1 * super.operator2;}
}/*** 除法计算器类,继承自计算器抽象类,实现了除法运算*/
class DivideCalculator extends Calculator
{public DivideCalculator(double operator1, double operator2){super(operator1, operator2);}@Overridepublic double calculate(){if (super.operator2 == 0)throw new RuntimeException("除数不能为 0!");return super.operator1 / super.operator2;}
}

🐷 运行结果

在这里插入图片描述

2. 适配器模式

这段代码演示了适配器模式的一个常见用法,即通过继承或实现接口来提供一个统一的接口,即使底层的实现可能并不完整或不完全符合预期。在实际应用中,适配器模式通常用于将一个类的接口转换成客户端期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作

  • 接口不兼容:有人只会中文,有人只会英语,不兼容
  • 接口转换:实现翻译,自定义实现 中译英、法、日 接口

💖 AdapterDemo.java

// 适配器模式演示代码
public class AdapterDemo {public static void main(String[] args) {// 创建一个Speaker对象,该对象实现了Translate接口Speaker speaker = new Speaker() {@Overridepublic void toFrench() {System.out.println("翻译成法语");}@Overridepublic void toEnglish() {System.out.println("翻译成英语");}// 注意:这里没有实现toJapanese方法,因此会调用父类的实现// 如果父类也没有实现,那么会抛出异常@Overridepublic void toJapanese() {// 这里可以添加具体的实现,或者抛出异常System.err.println("暂未实现");}};// 调用Speaker对象的toEnglish方法speaker.toEnglish();// 调用Speaker对象的toFrench方法speaker.toFrench();// 调用Speaker对象的toJapanese方法speaker.toJapanese();}
}// 定义一个抽象类Speaker,它实现了Translate接口
abstract class Speaker implements Translate {// 实现Translate接口的toEnglish方法,但这里没有具体实现public void toEnglish() {System.err.println("暂未实现");}// 实现Translate接口的toFrench方法,但这里没有具体实现public void toFrench() {System.err.println("暂未实现");}// 实现Translate接口的toJapanese方法,但这里没有具体实现public void toJapanese() {System.err.println("暂未实现");}
}// 定义一个Translate接口,包含三个方法:toEnglish, toFrench, toJapanese
interface Translate {// 将内容翻译成英语public void toEnglish();// 将内容翻译成法语public void toFrench();// 将内容翻译成日语public void toJapanese();
}

🐷 运行结果

翻译成英语
翻译成法语
暂未实现

3. 单例模式

💖 SingletonDemo.java

class Singleton
{// 私有静态变量,用于保存类的唯一实例private static Singleton instance = null;//懒汉式单例// 在类加载时就创建实例,确保全局只有一个实例// 饿汉式单例( getInstance() 方法里无需 new 创建新的实例对象)// private static final Singleton instance = new Singleton();// 私有构造方法,防止外部通过new创建多个实例private Singleton(){}// 公共静态方法,提供全局访问点public static Singleton getInstance(){// 双重检查锁定,确保线程安全if (instance == null){synchronized (Singleton.class){if (instance == null){instance = new Singleton();}}}return instance;}// 示例方法,可以在这里添加需要单例执行的业务逻辑public void dSsomething(){System.out.println("singleton is doing something.");}
}public class SingletonDemo
{public static void main(String[] args){// 通过geIinstance方法获Ssingleton的唯一实例Singleton singleton = Singleton.getInstance();singleton.dSsomething();}
}

运行结果

singleton is doing something.

💖 EnumSingletonDemo.java

由于枚举类型的实例在类加载时就被初始化,因此可以确保 Singleton 类只有一个实例。枚举的构造函数是私有的,所以不能从类的外部创建枚举的实例。

在这里插入图片描述

enum SingletonEnum
{INSTANCE; // 唯一的枚举实例// 示例方法,可以在这里添加需要单例执行的业务逻辑public void doSomething(){System.out.println("SingletonEnum is doing something.");}
}public class EnumSingletonDemo
{public static void main(String[] args){// 直接通过枚举类型调用方法SingletonEnum.INSTANCE.doSomething();}
}

运行结果

SingletonEnum is doing something.

三、总结

简单工厂模式

问题: 违反开闭原则,工厂类职责重。
解决: 使用反射、配置文件或工厂方法模式。
小结: 适用于产品类少,创建逻辑简单。复杂度高时,可采用工厂方法模式。

适配器模式

问题: 代码复杂度增加,性能问题。
解决: 使用对象组合、代理模式、泛型。
小结: 解决接口不兼容问题,但可能增加复杂度和性能开销。

单例模式

问题: 全局访问点,线程安全问题。
解决: 使用枚举、双重检查锁定、静态内部类。
小结: 确保类唯一实例,提供全局访问点。枚举实现简单且线程安全。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/589748.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶传感器:传感的本质

自动驾驶传感器:传感的本质 附赠自动驾驶学习资料和量产经验:链接 0. 前言 这个系列的背景是:工作时候需要攒一台数据采集车辆,那段时间需要熟悉感知硬件,写了不少笔记,都是些冗长的文章,感兴…

Vue3从入门到实战:路由的query和params参数

在Vue 3中,我们可以通过路由的查询参数来传递数据。这意味着我们可以在不同的页面之间传递一些信息,以便页面可以根据这些信息来显示不同的内容或执行不同的操作。 查询参数的使用方式类似于在URL中添加附加信息,以便页面之间可以根据这些信息…

vue3源码解析——watch和watchEffect区别

watch和watchEffect是Vue 3.0中新增的两个响应式API,用于监听数据的变化。watch适用于需要获取新值和旧值,或者需要懒执行的场景,而watchEffect适用于需要监听多个数据源,并且需要立即执行的场景。它们之间的区别如下:…

【Linux】详解动静态库的制作和使用动静态库在系统中的配置步骤

一、库的作用 1、提高开发效率,让开发者所有的函数实现不用从零开始。 2、隐藏源代码。 库其实就是所有的.o文件用特定的方式进行打包形成一个文件,各个.o文件包含了源代码中的机器语言指令。 二、动态库和静态库的制作和使用 2.1、静态库的制作和使用…

美创科技获浙江省网络空间安全协会多项荣誉认可

4月2日,浙江省网络空间安全协会第二届会员大会第一次会议在杭州隆重召开,近180家会员单位代表、数十位特邀专家、嘉宾莅临现场。浙江省委网信办副主任马晓军出席会议并致辞,本次大会由协会秘书长吴铤主持。 凝心聚力,继往开来&…

ViveNAS性能调试笔记(一)

ViveNAS是一个开源的NAS文件服务软件,有一套独立自创的架构,ViveNAS希望能做到下面的目标: - 能支持混合使用高性能的介质(NVMe SSD)和低性能介质(HDD,甚至磁带)。做到性能、成本动态均衡。因此ViveNAS使用…

C++--类的定义

一.类的定义 class 类名 { private:成员属性或成员函数 protected:成员属性或成员函数 public:成员属性或成员函数 };补充: (1)class是声明类的关键字,class后跟类名。类名一般首字母大写。 (2)类包括成员…

怎样在Linux搭建NTP服务器

搭建 NTP(Network Time Protocol)服务器可以帮助你在局域网内提供时间同步服务,让网络中的设备都使用统一的时间。以下是在 Linux 系统上搭建 NTP 服务器的基本步骤: 安装 NTP 服务器软件: 在终端中执行以下命令安装 N…

【爬虫框架Scrapy】02 Scrapy入门案例

接下来介绍一个简单的项目,完成一遍 Scrapy 抓取流程。通过这个过程,我们可以对 Scrapy 的基本用法和原理有大体了解。 1. 本节目标 本节要完成的任务如下。 创建一个 Scrapy 项目。 创建一个 Spider 来抓取站点和处理数据。 通过命令行将抓取的内容…

Gemini即将收费,GPT无需注册?GPT3.5白嫖和升级教程

🌐Gemini 即将开始收费 开发者“白嫖”的好日子到头了 - Gemini将开始收费,影响使用Google AI for Developers提供的Gemini API的用户。 - Gemini API将引入按量付费定价,需要注意新的服务条款。 - 用户需在5月2日之前停止使用Gemini API和Go…

redis事务(redis features)

redis支持事务,也就是可以在一次请求中执行多个命令。redis中的事务主要是通过MULTI和EXEC这两个命令来实现的。 MULTI命令用来开启一个事务,事务开启之后,所有的命令就都会被放入到一个队列中,最后通过一个EXEC命令来执行事务中…

【现代C++】委托构造函数

现代C中的委托构造函数(Delegating Constructors)是C11引入的特性,它允许一个构造函数调用同一个类中的另一个构造函数,以避免代码重复。这种特性在初始化对象时提高了代码的复用性和清晰性。 1. 基本用法 在同一个类中&#xf…