Java:设计模式

文章目录

  • 参考
  • 简介
  • 工厂模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式
    • 总结
  • 单例模式
    • 预加载
    • 懒加载
    • 线程安全问题
  • 策略模式

参考

知乎

简介

总体来说设计模式分为三类共23种。

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

工厂模式

简单工厂模式

定义了一个创建对象的类,由这个类来封装实例化对象的行为。
如下,Pizza工厂生产chesse pepper greek三种类型的pizza,所有创建pizza对象的行为都要通过SimplePizzaFactory这个类完成。

public class SimplePizzaFactory {public Pizza CreatePizza(String ordertype) {Pizza pizza = null;if (ordertype.equals("cheese")) {pizza = new CheesePizza();} else if (ordertype.equals("greek")) {pizza = new GreekPizza();} else if (ordertype.equals("pepper")) {pizza = new PepperPizza();}return pizza;}
}

工厂方法模式

简单工厂模式有一个问题是对象的创建依赖工厂类本身,如果要拓展程序必须对工厂类进行修改。
可以定义一个创建对象的抽象方法,并创建多个不同的工厂类实现该抽象方法,这样需要增加新功能时直接增加新的工厂类即可,如下。

// OrderPizza中的抽象方法
abstract Pizza createPizza();// 伦敦和纽约两个工厂实现抽象方法
public class LDOrderPizza extends OrderPizza {Pizza createPizza(String ordertype) {Pizza pizza = null;if (ordertype.equals("cheese")) {pizza = new LDCheesePizza();} else if (ordertype.equals("pepper")) {pizza = new LDPepperPizza();}return pizza;}
}
public class NYOrderPizza extends OrderPizza {Pizza createPizza(String ordertype) {Pizza pizza = null;if (ordertype.equals("cheese")) {pizza = new NYCheesePizza();} else if (ordertype.equals("pepper")) {pizza = new NYPepperPizza();}return pizza;}}

这个模式的好处是如果想增加功能,只需新增实现类即可。

抽象工厂模式

上述模式抽象程度仍不足,如客户想吃伦敦工厂的pizza,还需亲自调用伦敦工厂的createPizza方法。可以进一步优化,使用户只需传入自己的需求作为参数即可,不用亲自寻找不同的工厂。

点单方法如下,只需向固定的对象传入不同参数即可。

public class PizzaStroe {public static void main(String[] args) {OrderPizza mOrderPizza;mOrderPizza = new OrderPizza("London");}
}

抽象工厂的接口如下

public interface AbsFactory {Pizza CreatePizza(String ordertype) ;
}

工厂实现如下

public class LDFactory implements AbsFactory {@Overridepublic Pizza CreatePizza(String ordertype) {Pizza pizza = null;if ("cheese".equals(ordertype)) {pizza = new LDCheesePizza();} else if ("pepper".equals(ordertype)) {pizza = new LDPepperPizza();}return pizza;}
}

总结

简单工厂模式就是建立一个实例化对象的类,在该类中对多个对象实例化。工厂方法模式是定义了一个创建对象的抽象方法,由子类决定要实例化的类。这样做的好处是再有新的类型的对象需要实例化只要增加子类即可。抽象工厂模式定义了一个接口用于创建对象族,而无需明确指定具体类。抽象工厂也是把对象的实例化交给了子类,即支持拓展。同时提供给客户端接口,避免了用户直接操作子类工厂。

单例模式

确保一个类最多只有一个实例,并提供一个全局访问点。可以分为预加载和懒加载两种。

预加载

在使用单例对象之前先加载其到内存

public class PreloadSingleton {public static PreloadSingleton instance = new PreloadSingleton();//其他的类无法实例化单例类的对象private PreloadSingleton() {};public static PreloadSingleton getInstance() {return instance;}
}

懒加载

为了避免内存浪费,可以等用到该单例对象的时候再创建。

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

线程安全问题

预加载可以保证线程安全,懒加载无法保证线程安全,因为if判断后执行代码是非原子性的,而且new操作内部也无法保证顺序性,因为创建一个对象分三步

memory=allocate();//1:初始化内存空间ctorInstance(memory);//2:初始化对象instance=memory();//3:设置instance指向刚分配的内存地址

jvm为了提高程序执行性能,会对没有依赖关系的代码进行重排序,上面2和3行代码可能被重新排序。我们用两个线程来说明线程是不安全的。线程A和线程B都创建对象。其中,A2和A3的重排序,将导致线程B在B1处判断出instance不为空,线程B接下来将访问instance引用的对象。此时,线程B将会访问到一个还未初始化的对象(线程不安全)。
在这里插入图片描述
可以使用synchronized关键字保证线程安全,如果在getInstance函数上加此关键字,那么无论有没有初始化实例都会影响其他线程的执行,出于性能考虑,把关键字加到if判空的语句块内,保证instance没有实例化时才加锁。然后还需使用volatile关键字保证对象实例化过程的顺序性。

public class Singleton {private static volatile Singleton instance = null;private Singleton() {};public static synchronized Singleton getInstance() {if (instance == null) {synchronized (instance) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使得他们可以相互替换,且算法的变化不会影响到客户。
在这里插入图片描述
例:实现一个加减的功能类图如下
在这里插入图片描述
抽象策略角色定义如下

public interface Strategy {public int calc(int num1,int num2);
}

具体策略角色继承于抽象策略角色,分别实现了加减法。

public class AddStrategy implements Strategy {@Overridepublic int calc(int num1, int num2) {// TODO Auto-generated method stubreturn num1 + num2;}}
public class SubstractStrategy implements Strategy {@Overridepublic int calc(int num1, int num2) {// TODO Auto-generated method stubreturn num1 - num2;}

环境角色引用抽象角色给客户端调用

public class Environment {private Strategy strategy;public Environment(Strategy strategy) {this.strategy = strategy;}public int calculate(int a, int b) {return strategy.calc(a, b);}}

客户端调用环境角色完成计算

public class MainTest {public static void main(String[] args) {Environment environment=new Environment(new AddStrategy());int result=environment.calculate(20, 5);System.out.println(result);Environment environment1=new Environment(new SubstractStrategy());int result1=environment1.calculate(20, 5);System.out.println(result1);}}

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

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

相关文章

Function与Module的差异与应用场景,symbolic() 和 forward() 是什么关系?

Function与Module的差异与应用场景 Function与Module都可以对pytorch进行自定义拓展,使其满足网络的需求,但这两者还是有十分重要的不同: Function一般只定义一个操作,因为其无法保存参数,因此适用于激活函数、pooli…

Unity构建详解(1)——SBP介绍

【前言】 Unity的资源工作流程分为导入、创建、构建、分发、加载。我们说的是其中的构建步骤。 构建是指将项目工程中的资源文件和代码整合程可执行文件的过程,构建的结果是生成可执行文件,在win平台上是exe,在Android平台上是apk&#xff…

基于浏览器localStorage作为数据库完成todolsit项目

一、文章内容 TodoList结构搭建HTML代码 TodoList样式编写Css代码 TodoList行为表现JavaScript代码 二、项目展示 项目介绍 Todolist是一个基于B/S模式开发的待办事项软件,主要功能是离线记录用户的待办事项和已经完成的事情,基于htmlcssjs实现&am…

Superset二次开发之PostgreSQL 存储库介绍

Apache Superset 使用 PostgreSQL 作为其默认的元数据数据库,来存储关于数据源、图表、仪表盘、用户及其权限等信息。下面是列出的一些主要表的功能和作用的简介: 权限和角色 ab_permission: 存储权限,如“可以访问仪表板”、“可以执行SQL查询”等。ab_permission_view: 将…

Mysql——索引下推

MySQL的索引下推(Index Condition Pushdown, ICP)是一种查询优化技术,它允许MySQL在存储引擎层执行部分WHERE子句中的过滤条件,而非全部在MySQL服务器层执行。这使得在扫描索引过程中就可以剔除不满足条件的记录,从而减…

【C++】---string的模拟

【C】---string的模拟 一、string类实现1.string类的构造函数2.swap()函数3.拷贝构造函数4.赋值运算符重载5.析构6.迭代器7.operator[ ]8.size9.c_str()10.reserve()11.resize()12.p…

flutter 局部view更新,dialog更新进度,dialog更新

局部更新有好几种方法,本次使用的是 StatefulBuilder 定义 customState去更新对话框内容 import package:flutter/cupertino.dart; import package:flutter/material.dart;class ProgressDialog {final BuildContext context;BuildContext? dialogContext;double _…

【DL经典回顾】激活函数大汇总(四十一)(SinReLU附代码和详细公式)

激活函数大汇总(四十一)(SinReLU附代码和详细公式) 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里,激活函数扮演着不可或缺的角色,它们决定着神经元的输出,并且影响着网络的学习能…

Oracle函数6—递归查询(start with...connect by、sys_connect_by_path、level)

文章目录 一、准备数据二、基本使用三、level函数四、获取完整的全树路径 一、准备数据 创建表 CREATE TABLE TEST_ORG (ID VARCHAR2(64) NOT NULL PRIMARY KEY,NAME VARCHAR2(200),PARTEN_ID VARCHAR2(64) ); comment on column TEST_ORG.ID is 主键; comment on column TES…

C语言经典例题(2) --- 阶乘、斐波那契数、9*9乘法表、字符串逆序、求和

文章目录 1.求n的阶乘。(不考虑溢出)2.求第n个斐波那契数。&#xff08;不考虑溢出&#xff09;3.屏幕上输出9*9乘法口诀表4.字符串逆序(递归实现)5.计算一个数的每位之和(递归实现) 1.求n的阶乘。(不考虑溢出) #include <stdio.h>int fac(int n);int main() {int n 0;…

8节点空间壳单元Matlab有限元编程 | 曲壳单元 | 模态分析 | 3D壳单元 | 板壳理论| 【源代码+理论文本】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

Mysql的行级锁

MySQL 中锁定粒度最小的一种锁&#xff0c;是 针对索引字段加的锁 &#xff0c;只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小&#xff0c;并发度高&#xff0c;但加锁的开销也最大&#xff0c;加锁慢&#xff0c;会出现死锁。行级锁和存…

数据结构面试常见问题之Insert or Merge

&#x1f600;前言 本文将讨论如何区分插入排序和归并排序两种排序算法。我们将通过判断序列的有序性来确定使用哪种算法进行排序。具体而言&#xff0c;我们将介绍判断插入排序和归并排序的方法&#xff0c;并讨论最小和最大的能区分两种算法的序列长度。 &#x1f3e0;个人主…

Postman接口做关联测试的方法步骤

应用场景 假设下一个接口登录需要上一个接口的返回值&#xff0c;例如请求需要先登录获取到token&#xff0c;下一个请求要携带对应的token才能进行请求 方法&#xff1a;通过设置全局变量/环境变量 方法一&#xff1a;设置全局变量 1.先请求登录接口&#xff0c;请求成功之后…

力扣Lc20--- 202.快乐数(java版)-2024年3月20日

1.题目 2.知识点 &#xff08;1&#xff09;while (seen.contains(n) false) { // 循环体 } 与 !seen.contains(n) 等同 &#xff08;2&#xff09; 当传入数字 19 给 isHappy(19) 方法时&#xff0c;下面是每一行代码的执行过程&#xff1a; 初始化一个空的 HashSet&#…

32.网络游戏逆向分析与漏洞攻防-游戏网络通信数据解析-网络数据分析原理与依据

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;31.其它消息的实…

(七)事件组

一、概念 &#xff08;1&#xff09;用于实现任务与任务、任务与中断之间通信和同步&#xff0c;无数据传输 &#xff08;2&#xff09;不同于信号量的是&#xff0c;信号量是一对一的&#xff0c;而事件可以是一对多和多对一的&#xff0c;即一个任务等待多个事件或多个任务等…

el-table的border属性失效问题解决方案

目录 问题&#xff1a; 使用的代码&#xff1a; 官方文档的说明&#xff1a; 可能的问题所在&#xff1a; 关于使用了作用域插槽&#xff1a; a.自定义内容的样式覆盖&#xff1a; b.表格结构的改变&#xff1a; 解决方案&#xff1a; 通过css样式解决&#xff1a; 下面…

打流仪/网络测试仪这个市场还能怎么卷?

#喝了点&#xff0c;码点字# 以下为个人观点&#xff0c;看看就好&#xff0c;如有冒犯&#xff0c;私信删稿 都有哪些厂商在做打流仪/网络测试仪 -洋品牌&#xff1a;思博伦/Viavi-Spirent&#xff0c;是德/Keysight-Ixia&#xff0c;信雅纳/Lecroy-Xena&#xff0c; -国产…

java输入语句scanner

在Java中&#xff0c;Scanner 类是 java.util 包中的一个类&#xff0c;它用于获取用户的输入。要使用 Scanner 类&#xff0c;你首先需要导入这个类&#xff0c;然后创建一个 Scanner 对象&#xff0c;通常命名为 scanner。你可以使用这个对象来读取用户从键盘输入的数据。 以…