常用设计模式介绍

news2025/2/26 3:39:06

java设计模式类型

  • 创建型模式:将对象的创建与使用分离

  • 结构型模式:如何将类和对象按照某种布局组成更大的格局

  • 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务

23种设计模式介绍

1.单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局

访问点供外部获取该实例,其拓展是有限多例模式。

2.原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆

出多个和原型类似的新实例。

3.工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子

类决定生产什么产品。

4.抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个

子类可以生产一系列相关的产品。

5.建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然

后根据不同需要分别创建它们,最后构建成该复杂对象。

6.代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客

户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

7.适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,

使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

8.桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组

合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

9.装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功

能。

10. 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子

系统更加容易被访问。

11. 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复

用。

12. 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象

和组合对象具有一致的访问性。

13. 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算

法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定

义该算法的某些特定步骤。

14. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它

们可以相互替换,且算法的改变不会影响使用算法的客户。

15. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任

和执行请求的责任分割开。

16. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下

一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

17. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能

力。

18. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改

变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。

19. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互

关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

20. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数

据,而不暴露聚合对象的内部表示。

21. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个

元素提供多种访问方式,即每个元素有多个访问者对象访问。

22. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对

象的内部状态,以便以后恢复它。

23. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的

解释方法,即解释器

常用设计模式:

单例模式

定义:在有些系统中,为了节省内存资源、保证数据内容的一致性,创建一个实例共大家享用,例如:Runtime类

特点

  • 单例只有一个实例对象

  • 该单例对象必须由单例类自行创建

  • 单例;类对外提供一个公共的方法进行访问

  1. 饿汉模式

在这里拿window为例给大家进行演示

public class Window {
    /*饿汉式单例:在类加载的时候的初始化实例(static)
    * 因为创建的实例只有一个,所以不存在线程安全问题*/
    private static Window window=new Window();

    public Window getWindow(){
             return window;
    }
}
public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                System.out.println(new Window().getWindow());//获得是同一个对象
            }).start();
        }
    }
}
  1. 懒汉模式

public class Window {
    /*懒汉式单例:
    * 在类加载的时候,不创建对象,在使用时进行创建
    * 这时,生成对象的数量就需要我们自己来进行控制
    * 但是懒汉式单例会出现线程安全问题:在多线程访问时,可能会有多个线程同时进行到if中,就会创建出多个对象
    * 在并发的时候,会出现指令重排的情况,所以用volatile防止指令重排,避免造成错误*/
   
    private static volatile Window window;
    public Window getWindow(){
        try {
            //增加休眠增加并发的几率
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
          //1.0版本给方法上锁,虽然可行,但是效率太低,每次只能运行一个线程
          // if(windows==null){  1.1版本 进入if之后上锁,这种上锁起不到多个线程公用一个对象实例的作用,一个执行完之后,另外一个线程进入重新创建一个实例对象
          // synchronized (Windows.class){
          // window=new Window()}
//}
        //最终版本,双重判断,公用一个对象实例
        if(window==null){
            synchronized (Window.class){
                if (window==null){
                    window=new Window();
                }

            }
        }
        return window;
    }
}
public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                System.out.println(new Window().getWindow());
            }).start();
        }
    }
}

工厂模式

  1. 简单工厂:适用于产品子类较少,不符合开闭原则

模式中包含的角色及其职责

工厂:负责逻辑运算以及创建所需要的产品

抽象产品:描述所有实例共有的接口或者是抽象类

具体产品抽象:是简单工厂的创建目标

代码实现:

//Car接口
public interface Car {

      void run();
}
//CarFactory工厂类
public class CarFactory{
     public static Car createCar(String name){
            if(name.equals("aodi")){
                return new Aodi();
            }
            if(name.equals("bmw")){
                return new Bmw();
            }
            return null;
     }
}
//实现类
public class Aodi implements Car{

    @Override
    public void run() {
        System.out.println("奥迪汽车行驶");
    }
}
//实现类
public class Bmw implements Car{

    @Override
    public void run() {
        System.out.println("宝马汽车行驶");
    }

}
//客户端
public class Test {

    public static void main(String[] args) {
  //每次增加子类类型的时候,需要对代码进行修改,不符合开闭原则,适用于子类较少或者是不容易修改的项目中
  //优点:客户端不负责对象的创建,由专门的工厂进行创建,客户端直需要对对象进行调用,实现创建和调用的分离,降低了代码的耦合度
  //缺点:如果增加或减少子类,需要对代码进行修改,违背了设计原则中的开闭原则,如果子类过多,会导致工厂非常庞大,违背了高内聚原则,不利于后期的维护
        Car bmw  = CarFactory.createCar("bmw");
        Car aodi  = CarFactory.createCar("aodi");

          bmw.run();
          aodi.run();
    }
}
  1. 工厂方式模式

对工厂也进行了抽象,将实际创建工作推迟到子类去完成

优点:客户端不负责创建对象的创建,而是由专门的工厂类完成,客户端只负责对象的调用,实现了创建和调用的分离,降低了客户端代码的难度,若增加和减少产品子类,不需要对工厂进行修改,直需要增加产品子类和工厂子类,符合开闭原则,即使产品子类过多也不会导致工厂类的庞大,利于后期的维护

缺点:需要些额外的代码,增加了工作量

抽象工厂模式

将同一品牌的物品放在一起进行生产,就好比你去生产联的大厂中既可以买到联想手机也可以买到联想电脑,不用将它们分别生产,造成资源浪费

优点:获取具体系列产品只需要通过具体的系列的工厂获取,无心关心创建的细节

原型模式:

在项目中,我们需要很多个实例,但是创建实例对象又很麻烦,所以觉得直接创建对象是一个不太明智的选择,所以我们经常在需要多次创建相同的对象的时候用到克隆(clone),为了提高创建速度

代理模式:

代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用,使得客户不能直接与真正的目标对象通信,代理对象是对象的代表,客户端通过代理对象对实际对象进行操作

  • 静态代理

特点:代理类实现一个接口,任何实现给接口的对象,都可以通过代理类进行代理,增加了通用性

优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展

缺点:代码量大,必须要有接口,再有代理

//Computer对象类
public class Compurter implements Huawei{

    @Override
    public void run() {
        System.out.println("华为电脑跑步机器");
    }

    @Override
    public void play() {
        System.out.println("华为电脑在玩");
    }
}
//customer客户端
public class customer {

    public static void main(String[] args) {
        Phone phone=new Phone();
        Compurter compurter=new Compurter();

        Proxy proxy1=new Proxy(phone);
        Proxy proxy=new Proxy(compurter);
        proxy.play();
        proxy1.run();
    }

}
//Huawei接口
public interface Huawei {
    public void run();
    public void play();
}
//Phone对象类
public class Phone implements Huawei{
    @Override
    public void run() {
        System.out.println("华为手机在跑步");
    }

    @Override
    public void play() {
        System.out.println("华为手机在玩");
    }


}
//Proxy代理对象
public class Proxy implements Huawei {
   Huawei huawei;

     public Proxy(Huawei huawei){
        this.huawei=huawei;
     }
    @Override
    public void run() {
            try {
                System.out.println("你是大坏蛋");
            } catch (Exception e) {

            } finally {
                System.out.println("终于完了");
            }


    }

    @Override
    public void play() {
       huawei.play();
    }
}
  • 动态代理

通过动态代理我们就不需要手动的创建代理类了,只需要编写一个动态处理就可以了,代理对象通过动态处理

jdk动态代理:

public class JdkProxy implements InvocationHandler {

    Object object;//真实对象,接收任何的目标类对象

    public JdkProxy(Object object){
        this.object=object;
    }
    /* 在动态代理类中调用目标类中的具体方法,动态的将代理对象对象
    * 目标类中要调用方法,以及方法中的参数传递过来
    *  Method method  动态获取的真正要执行的方法*/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        method.invoke(object);
        return proxy;
    }

    //真正意义上的运行时生成代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
    }
}

cg动态代理:

/*
 * 动态代理类
 */
public class CGLibProxy implements MethodInterceptor {
    
        private Enhancer enhancer = new Enhancer();
        
        public Object getProxy(Class<?> clazz){  
            enhancer.setSuperclass(clazz);  
            enhancer.setCallback(this);  
            return enhancer.create();  
        }  
        /*
         * 拦截所有目标类方法的调用 
         * 参数: 
         * obj  目标实例对象 
         * method 目标方法的反射对象 
         * args 方法的参数 
         * proxy 代理类的实例 
         */  
        public Object intercept(Object obj, Method method, Object[] args,  
                MethodProxy proxy) throws Throwable {
            //代理类调用父类的方法  
            System.out.println("开始事务");  
            Object obj1 = proxy.invokeSuper(obj, args);  
            System.out.println("关闭事务");  
            return obj1;  
        }
}

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

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

相关文章

linux高级命令之软件安装

软件安装学习目标能够使用apt-get命令安装软件1. 软件安装的介绍Ubuntu软件安装有两种方式:离线安装(deb文件格式安装&#xff09;在线安装(apt-get方式安装)2. deb文件格式安装是 Ubuntu 的安装包格式&#xff0c;可以使用 dpkg 命令进行软件的安装和卸载。命令说明dpkg安装和…

以“大数据”赋能产业链精准招商

​ 随着我国产业发展的不断迭代升级&#xff0c;传统招商模式的不足逐步凸显&#xff0c;侧重土地与税费优惠的同质化竞争招商以及来者不拒的无门槛型招商已经遏制了区域产业的发展&#xff0c;导致各产业园区很难形成产业集聚及持续的吸引力。在这样的大环境下&#xff0c;产业…

使用LogToHtml导出Airtest报告

simple_report接口&#xff0c;是个简化版的生成报告接口&#xff0c;如果仅仅需要在本地查看的话&#xff0c;用这个接口即可。 但是如果需要导出报告&#xff0c;即他人也可以正常查看&#xff0c;则需要用LogToHtml类。 参数解释 script_root&#xff0c;脚本路径 log_ro…

论一个上班族如何一次性通过PMP考试

PMP是我工作后考取的一个证书。从准备到通过&#xff0c;花了大约三个月的时间。我之前在某家互联网公司从事程序员的工作&#xff0c;工作一段时间后&#xff0c;天天敲着代码&#xff0c;改着bug&#xff0c;感觉比较迷茫&#xff0c;不知道未来的发展在哪里&#xff0c;都说…

Viper捐款7000万韩元,合计人民币是多少钱?

Viper捐款7000万韩元&#xff0c;合计人民币是多少钱&#xff1f; #2023LCK春季赛##英雄联盟# #Viper捐款7000万韩元# Viper向大田东区捐款 7000 万&#xff0c;成为大田荣誉协会 105 号会员。Viper选手从 2019 年开始一直向大田东区捐款&#xff0c;但是他不希望这件事被公开…

[VMware]Ubuntu18.04 网络图标消失

Ubuntu 18.04 网络图标消失运行环境问题解决NO.1 执行 sudo systemctl stop network-managerNO.2 执行 sudo rm /var/lib/NetworkManager/NetworkManager.stateNO.3 执行 sudo systemctl start network-managerNO.4 vi /etc/NetworkManager/NetworkManager.confNO.5 执行 sudo …

【Linux 多线程】线程的4大基础操作(创建、等待、终止、分离)

目录 1.线程的创建 2.线程等待 3.线程分离 线程共享一个地址空间 &#xff0c;把资源&#xff08;代码和数据&#xff09;化成若干份&#xff0c;供各个线程使用 线程的栈和上下文不是共享的以前学习的进程是具有一个线程的进程1.线程的创建 成功返回0&#xff0c;失败返回…

第一章:初始化react项目+antd+less

初始化react项目 我们首先使用react脚手架创建一个项目 Ant Design less creact-react-app中文文档 creact-react-app demo生产环境打包运行 当我们执行了 npm run build 打包后直接访问index.html 看效果白屏 这时候就需要安装一个serve包 npm install -g serve当我们安…

操作系统(二):死锁的检测,死锁的恢复和死锁的预防

文章目录零、什么是死锁一、死锁检测1. 对每种类型一个资源的死锁检测2. 对每种类型多个资源的死锁检测二、死锁恢复三、死锁预防四、死锁避免1 面向单个资源的银行家算法2 面向多个资源的银行家算法总结银行家算法的核心就是避免系统进行系统资源分配的不安全状态零、什么是死…

Zipkin : Golang 微服务全链路监控(二)

Zipkin : Golang 微服务全链路监控&#xff08;二&#xff09; Golang 微服务全链路监控实现 broker-service -> auth-service -> postgres dbzipkin 监控&#xff1a;需代码入侵 一、auth-service 通过 context 传递 span main.go package mainimport ("broke…

CSDN 编辑器 Marddown 语法备忘

原文链接&#xff1a;https://blog.csdn.net/blogdevteam/article/details/103478461 本文对其二次加工&#xff0c;增加渲染样式、补充例程、添加未收录的常用语法。 CSDN Markdown 编辑器遵循 CommonMark spec 语法规范。 快捷键 撤销&#xff1a;Ctrl/Command Z 重做&…

成都链安受邀参加第五届CCF中国区块链技术大会

2月10-12日&#xff0c;由中国计算机学会主办的&#xff0c;2023年国内首场大型区块链学术会议—第五届CCF中国区块链技术大会在无锡市成功举办&#xff0c;成都链安作为区块链安全头部企业受邀参加此次大会。大会上&#xff0c;成都链安创始人&CTO郭文生教授与锡东新城商务…

微信小程序开发(五)小程序代码组成2

微信小程序开发&#xff08;五&#xff09;小程序代码组成2 为了进一步加深我们对小程序基础知识的了解和掌握&#xff0c;需要更进一步的了解小程序的代码组成以及一些简单的代码的编写。 参考小程序官方的的代码组成文档&#xff1a;https://developers.weixin.qq.com/ebook?…

海量并发低延时 RTC-CDN 系统架构设计(上)

随着近几年音视频流媒体行业的持续发展&#xff0c;海量并发、低延时和低成本作为三大核心诉求依旧需要不断深挖&#xff0c;同时随着 RTC 和 CDN 这两种技术的界线越来越模糊&#xff0c;因此有必要从底层架构层面重新思考 RTC 与 CDN 的融合之道。本文将重点分享&#xff1a;…

通过 Colab 下载 Google Driver 上的大文件到内网服务器

这里写自定义目录标题1. 将 Google Driver 上的大文件下载到 Colab1.1 获取文件唯一的 fileID1.2 查看文件的 MD5 值1.3 获取 API 的 Access Token1.4 下载文件到 Colab2. 将文件从 Colab 下载到公网服务器3. 将文件从公网服务器下载到内网服务器4. 参考链接由于众所周知的原因…

【正点原子FPGA连载】第十章PS SYSMON测量温度电压实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十章PS SYSMON…

如何正确的在Flutter中添加webview

前言 为什么要在flutter中引入webview&#xff1f;这不是废话么&#xff0c;当然是为了加载一个网页&#xff0c;这不是移动端最基本的需求么&#xff0c;哈哈&#xff01;说的真不错&#xff0c;接下来我要是告诉你我的用法&#xff0c;你可能要大吃一惊。我的用处很简单&…

【音视频处理】码率、帧率越高越清晰?分辨率、像素、dpi之间是什么关系?码率的真实作用,I帧、B帧、P帧是什么

大家好&#xff0c;欢迎来到停止重构的频道。本期我们介绍一下视频的一些基础概念&#xff0c;如帧率、码率、分辨率、像素、dpi、视频帧、I帧、P帧、gop等。会解释多少码率是清晰的&#xff0c;是否帧率越高越流畅等问题。这些概念是比较杂乱的&#xff0c;我们按这样的顺序介…

Seata源码学习(四)-数据源代理

Seata源码分析-数据源代理 上节课我们分析了整体的Seata-AT模式的2PC执行流程&#xff0c;那么这节课我们要分析的就是在AT模式中的关键点&#xff0c;数据源代理 AT模式的核心点&#xff1a; 获取全局锁、开启全局事务解析SQL并写入undolog 那么上节课其实我们已经把第一步…

【目标检测】K-means和K-means++计算anchors结果比较(附完整代码,全网最详细的手把手教程)

写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大努力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 一、介绍 YOLO系列目标检测算法中基于anchor的模型还是比较多的,例如YOLOv3、YOLOv4、YOLOv5等,我们可以随机初始化a…