目录

  • 一、Java设计模式
    • 1、概述
    • 2 、优点
    • 3、java设计模式类型
  • 1、单例模式(Singleton)
    • (1)懒汉式单例
    • (2)饿汉式单例
  • 2、工厂模式(Factory Pattern )
    • 定义
    • 简单工厂
  • 3、代理模式
    • (1)静态代理
    • (2)动态代理
      • jdk代理
      • Cglib代理

一、Java设计模式

1、概述

在前辈们长期开发的过程中,为解决某一类问题,总结出的一种较为优化的代码设计结构。提高程序代码复用,扩展性,稳定性。
设计模式详述

2 、优点

  1. 可以提高程序员的思维能力、编程能力和设计能力。
  2. 使程序设计更加标准化、代码编制更加工程化,使开发效率大大提高,从而缩短软件的开发周期。
  3. 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。

3、java设计模式类型

  • 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式。
  • 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,提供了代理、适配器、桥接、装饰、外观、享元、组合 7 种结构型模式。
  • 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式。

1、单例模式(Singleton)

在整个程序中只允许有一个对象。
创建对象,使用构造方法,将构造方法私有化,只能在本类中创建,这样我们就可以控制数量,向外界提供一个公共的访问方法。

(1)懒汉式单例

package com.ffyc.database.javadesign.singleton.demo1;/** 懒汉式单例* 在类加载时,不会创建单例对象,在第一次访问时,才会去创建** 懒汉式单例有线程安全问题,必须要加锁处理*/
public class Singleton {//定义静态的private static Singleton instance;  //让构造函数为 private,这样该类就不会被实例化private Singleton (){}  //向外界提供获取实例的方法  加锁 synchronized 才能保证单例public static synchronized Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }
}

(2)饿汉式单例

/** 饿汉式单例* 一般又称为急切式单例* 在类加载时,就会创建此单例对象,这种写法不会出现线程安全问题*/
public class Singleton {//创建 Singleton 的一个对象private static Singleton instance = new Singleton();//让构造函数为 privateprivate Singleton(){}//获取唯一可用的对象public static Singleton getInstance(){return instance;}
}

2、工厂模式(Factory Pattern )

定义

  • 批量创建对象,将创建对象与使用对象分离,按照实际业务场景划分,工厂模式有2种不同的实现方式,分别是简单工厂模式抽象工厂模式

简单工厂

  • 我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果创建的产品不多,只需要创建一个工厂类。
  • 角色:
  1. 简单工厂:负责生产对象的
  2. 抽象产品:接口/抽象类 进行定义
  3. 具体产品:实现抽象类接口/抽象类的具体实现类以抽象来表示具体。

3、代理模式

eg:代理 —>代理商 (4s店,中介,商场)

  • 当用户不想或不能直接去访问目标对象,可以通过一个中间代理商在用户和目标之间起到一个中间作用。
  • 代理模式的主要优点有:
  1. 保护目标对象
  2. 对目标的功能进行扩展
  3. 将用户和目标进行分类,降低了耦合度
  • 模式的结构
  1. 抽象类 (Subject):通过接口或抽象类代理对象实现的业务方法。
  2. 真实目标(Real Subject): 实现了抽象主题中的具体业务。
  3. 代理类(Proxy):提供与真实目标相同的接口,内部含有对真实主题的引用,可以访问、控制或扩展真实主题的功能。

(1)静态代理

  • 静态代理一般适用于关系是固定的,代理某类事务必须实现接口,如果需要代理多个目标对象,那么就需要实现更多的接口,后期维护比较麻烦。
    eg:

  • BaseDao

/*Dao接口,定义保存功能*/
public interface BaseDao {void save();}
  • UserDaoImpl
package com.ffyc.database.javadesign.proxy.staticproxy;/*实际功能实现类*/
public class UserDaoImpl implements BaseDao {@Overridepublic void save() {System.out.println("UserDaoImpl:save()");}}
  • StaticDaoProxy
package com.ffyc.database.javadesign.proxy.staticproxy;/** 静态代理类*/
public class StaticDaoProxy implements BaseDao {//接收所有实现BaseDao接口的实现类对象private BaseDao baseDao;// 将被代理者的实例传进动态代理类的构造函数中public StaticDaoProxy(BaseDao baseDao) {this.baseDao = baseDao;}//代理他们实现功能,可以在调用前,调用后额外添加功能.@Overridepublic void save() {System.out.println("before");//额外的扩展功能baseDao.save();//调用的是真实目标中的方法System.out.println("after");}}
  • Test
package com.ffyc.database.javadesign.proxy.staticproxy;public class Test {public static void main(String[] args) {//把实际执行者交给代理对象管理即可StaticDaoProxy subject = new StaticDaoProxy(new UserDaoImpl());subject.save();}
}

(2)动态代理

动态代理中,代理类并不是在 Java 代码中实现,而是在运行时期生成,相比静态代理,动态代理可以很方便的对委托类的方法进行统一处理,如添加方法调用次数、添加日志功能等等,动态代理分为 jdk 动态代理和 cglib 动态代理。

jdk代理

实现原理:使用的是java反射机制(java.lang.reflect.Proxy),可以动态获取目标类中代理的方法,不需要代理类指定的去实现某些抽象接口,代理的扩展性好。动态生成代理对象,要求目标类必须有实现接口。
eg:

  • 对于静态代理下改变

  • DynamicDaoProxy

package com.ffyc.database.javadesign.proxy.dynamicproxy.jdk;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/** 动态代理类*/
public class DynamicDaoProxy implements InvocationHandler {// 被代理类的实例private Object object; //baseDao-->object(任意的)// 将被代理者的实例传进动态代理类的构造函数中public DynamicDaoProxy(Object object) {this.object = object;}/** 覆盖InvocationHandler接口中的invoke()方法*    Object proxy 表示代理对象*    Method method 代理对象中的方法*     Object[] args  表示代理方法中的参数* 更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构* 的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到* 控制被代理对象的行为,下面的before、after就是我们可以进行特殊* 代码切入的扩展点了。*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before");Object result = method.invoke(object, args);System.out.println("after");return result;}
}
  • Test
package com.ffyc.database.javadesign.proxy.dynamicproxy.jdk;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {//我们要代理的真实对象UserDaoImpl userDaoImpl = new UserDaoImpl();//我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的InvocationHandler dynamicProxy = new DynamicDaoProxy(userDaoImpl);/** 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象* 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了* 第三个参数dynamicProxy, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上*///动态生成的代理对象BaseDao baseDao = (BaseDao) Proxy.newProxyInstance(dynamicProxy.getClass().getClassLoader(), userDaoImpl.getClass().getInterfaces(), dynamicProxy);//mybatis 接口代理 访问 接口中的方法baseDao.save();}
}
  • 动态代理总结
    虽然相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。

Cglib代理

  • 动态字节码技术,可以在运行中为目标类动态生成一个子类,进行方法拦截,从而添加增强功能。不能代理final所修饰的类,目标类可以不实现任何接口。
    -Cglib子类代理实现方法:
  1. 需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所以直接引入 spring-core-xxx.jar 即可.
  2. 引入功能包后,就可以在内存中动态构建子类
  3. 代理的类不能为 final,否则报错
  4. 目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
package database.javadesign.proxy.dynamicproxy.cglib;import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;- CGLibProxy
/** 动态代理类*/
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 代理类的实例 */  @Overridepublic 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;  }
}
  • UserDaoImpl
//具体主题
public class UserDaoImpl {public void save() {System.out.println("UserDaoImpl:save()");}}

  • spring中两种实现都支持,可以根据目标类是否实现接口,自动选择动态方式。

Java设计模式(java design patterns)相关推荐

  1. 设计模式(Design Patterns)详解

    设计模式(Design Patterns) --可复用面向对象软件的基础一般会用到的: Factory( 工厂模式) Singleton(单例模式) 这两个比较多 Proxy(代理模式) Adapte ...

  2. 视频教程-全新150集通俗易懂的Java设计模式-Java

    全新150集通俗易懂的Java设计模式 张长志技术全才.擅长领域:区块链.大数据.Java等.10余年软件研发及企业培训经验,曾为多家大型企业提供企业内训如中石化,中国联通,中国移动等知名企业.拥有丰 ...

  3. 架构与设计 之一 C 嵌入式设计模式(Design Patterns for Embedded Systems in C)的学习记录

    唉   时至今日,已经不知道在嵌入式的道路上到底挣扎了多少个岁月,总感觉要"病入膏肓"了.此间总是不时出现一些疑惑:人家搞 Java.搞 C# 的动不动就是什么架构 / 框架的,搞 ...

  4. 架构设计 之一 C 嵌入式设计模式(Design Patterns for Embedded Systems in C)学习笔记

    前言   时至今日,已经不知道在嵌入式的道路上到底挣扎了多少个岁月,总感觉要"病入膏肓"了.此间总是不时出现一些疑惑:人家搞 Java.搞 C# 的动不动就是什么架构 / 框架的, ...

  5. 什么是设计模式(Design Patterns)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 设计模式于己于他人于系统都是多赢的,项目中合理的运用设计模式可以完美的解决很多问题,每种模 ...

  6. 快速学习23种设计模式思想Design Patterns

    1.factory(工厂)追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德 基,只管向服务员说"来四个鸡翅"就行了 ...

  7. java 设计模式 示例_Java设计模式–示例教程

    java 设计模式 示例 Design Patterns are very popular among software developers. A design pattern is a well- ...

  8. Design Patterns in Java

    <Design Patterns in Java> 作者:Steven John Metsker,William C. Wake 出版日期:2006-04-28 语言:English 版本 ...

  9. Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  10. Java设计模式详解

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

最新文章

  1. 一个简单的程序来使用WiredTiger 存储引擎
  2. 使用 .NET 实现 Ajax 长连接
  3. formRef=React.createRef() this.formRef.current为null
  4. POP3、SMTP端口(SSL、TSL)
  5. 列举Python中常见的内置函数
  6. [luoguP2801] 教主的魔法(二分 + 分块)
  7. 天猫整站SSM-分页-herf(做个人学习笔记整理用)
  8. 类文件Android 代码混淆 以及 反编译 的实现类文件
  9. linux 正则匹配文件名,shell 正则表达式与文件名匹配
  10. Exploring Complementary Strengths of Invariant and Equivariant Representations for Few-Shot Learning
  11. 《方块方舟》自定义服务器工具,方舟方块世界服务器建立方法
  12. godaddy plesk mysql 连接 2014_GoDaddy Plesk主机安装Discuz论坛需要注意的问题 | Godaddy美国主机中文指南...
  13. lawson算法_案例研究:Lawson合并后整合架构的新方法
  14. 计算机结构原理与组成ppt,计算机组成原理与系统结构课件.ppt
  15. 遗传算法神经网络预测彩票
  16. python读取DataFrame的某行或某列
  17. 智启ICT产业未来!卡奥斯“5G+工业互联网”创新成果获权威认可
  18. 迅雷,qq旋风等下载链接加密算法解析
  19. Spring的面试终极问答
  20. intermec介绍

热门文章

  1. Java— 齐头并进完成任务—多线程
  2. 如何批量在excel中将中文转换为汉语拼音(Excel文字转拼音两种方法)
  3. 在GPU上运行MATLAB程序
  4. 复制网页上不能复制的文字
  5. 21考研:你是为了什么考研?
  6. 半监督学习:semi-supervised learning 直推学习:transductive learning 主动学习:active learning
  7. 计算机网络网卡作用是什么,什么是网卡?它的作用是什么?
  8. 速达财务软件未能连接服务器,速达3000财务软件使用常见问题
  9. 【计算机网络】网络层——IPv6/IP组播/移动IP
  10. 第九周项目——穷举法之三色球