设计模式:是一种思维方式,组织类的方式。

  • 单例模式:Singleton模式。指一个类,仅能创建唯一实例。
  • 实现
  • 使用类变量,提前创建类的实例,饿汉式-不管用不用到,都会在内存中占据空间。线程安全的。
    一上来我就把对象给new好了,来了可以直接“吃” 了
package javaPro1;public class Single {//1、私有化构造函数private Single() {}// 2、new一个Single对象private static final Single SINGLE = new Single();// 3、创建一个方法,让外面的类可以拿到对象的引用public static Single getInstance() {return SINGLE;}
}
package javaPro1;public class Single {//线程安全的private Single() {} public static Single getInstance() {return SingleHolder.SINGLE;}private  static class SingleHolder{private static final Single SINGLE = new Single();}}
  • 懒汉式:不会在内存中创建空间,返回唯一变量时,才进行创建。非线程安全的。
    (要是有人问单例的延迟加载方式值得就是这种方式)一开始我不给你new对象,你来找我,我再给你new对象。
package javaPro1;public class Single {//1、私有化构造函数private Single() {}// 2、声明一个对象的引用private static Single SINGLE;// 3、判断一下,如果对象为null,创建对象public static Single getInstance() {if(SINGLE == null) {SINGLE = new Single();}return SINGLE;}
}
  • 懒汉式,保证线程安全-双检锁
package javaPro1;public class Single {//1、私有化构造函数private Single() {}// 2、声明一个对象的引用private volatile static Single SINGLE;// 3、判断一下,如果对象为null,创建对象public static Single getInstance() {//保证线程安全if(SINGLE == null) {synchronized (SINGLE) {//双检锁if(SINGLE == null) {SINGLE = new Single();}}          }return SINGLE;}
}
  • 测试类
package javaPro1;public class Test1 {public static void main(String[] args) {Single m1 = Single.getInstance();Single m2 = Single.getInstance();System.out.println(m1 == m2);//true}
}

以下内容参考自菜鸟教程

  • 工厂模式:创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
  • 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
  • 主要解决:主要解决接口选择的问题。
  • 何时使用:我们明确地计划不同条件下创建不同实例时。
  • 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
  • 关键代码:创建过程在其子类执行
  • 实现
  • 步骤 1、创建一个接口:
public interface Shape {void draw();
}
  • 步骤 2、创建实现接口的实体类。
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}
public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}
  • 步骤3、创建一个工厂,生成基于给定信息的实体类的对象。
public class ShapeFactory {//使用 getShape 方法获取形状类型的对象public Shape getShape(String shapeType){if(shapeType == null){return null;}        if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle();} else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle();} else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square();}return null;}
}
  • 步骤4、使用该工厂,通过传递类型信息来获取实体类的对象。
public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();//获取 Circle 的对象,并调用它的 draw 方法Shape shape1 = shapeFactory.getShape("CIRCLE");//调用 Circle 的 draw 方法shape1.draw();//获取 Rectangle 的对象,并调用它的 draw 方法Shape shape2 = shapeFactory.getShape("RECTANGLE");//调用 Rectangle 的 draw 方法shape2.draw();//获取 Square 的对象,并调用它的 draw 方法Shape shape3 = shapeFactory.getShape("SQUARE");//调用 Square 的 draw 方法shape3.draw();}
}
  • 步骤5、执行程序,输出结果:

  • 代理模式:在代理模式(Proxy Pattern)中,某个类代理另-一个类的全部或部分操作,代理的过程中,有可能对目标类的职责进行功能的改变,校验,或增强。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
  • 意图:为其他对象提供一种代理以控制对这个对象的访问。
  • 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
  • 何时使用:想在访问一个类时做一些控制。
  • 如何解决:增加中间层。
  • 关键代码:实现与被代理类组合。
  • 应用实例: 1、Windows 里面的快捷方式。 2、猪八戒去找高翠兰结果是孙悟空变的,可以这样理解:把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,猪八戒访问高翠兰的时候看不出来这个是孙悟空,所以说孙悟空是高翠兰代理类。 3、买火车票不一定在火车站买,也可以去代售点。 4、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。 5、spring aop。
  • 实现
  • 步骤1、创建一个接口
public interface Image {void display();
}
  • 步骤2、创建实现接口的实体类。
public class RealImage implements Image {private String fileName;public RealImage(String fileName){this.fileName = fileName;loadFromDisk(fileName);}@Overridepublic void display() {System.out.println("Displaying " + fileName);}private void loadFromDisk(String fileName){System.out.println("Loading " + fileName);}
  • 步骤3、当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。
public class ProxyPatternDemo {public static void main(String[] args) {Image image = new ProxyImage("test_10mb.jpg");// 图像将从磁盘加载image.display(); System.out.println("");// 图像不需要从磁盘加载image.display();  }
}
  • 步骤4、执行程序,输出结果

静态代理

以下内容参考自博客园周有才

  • 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
  • 示例:我们平常去电影院看电影的时候,在电影开始的阶段是不是经常会放广告呢?电影是电影公司委托给影院进行播放的,但是影院可以在播放电影的时候,产生一些自己的经济收益,比如卖爆米花、可乐等,然后在影片开始结束时播放一些广告。
  • 现在用代码来进行模拟。
  • 首先得有一个接口,通用的接口是代理模式实现的基础。这个接口我们命名为 Movie,代表电影播放的能力。
package com.pro2;public interface Movie {void play();
}
  • 然后,我们要有一个真正的实现这个 Movie 接口的类,和一个只是实现接口的代理类。这个表示真正的影片。它实现了 Movie 接口,play() 方法调用时,影片就开始播放。那么 Proxy 代理呢?
package com.pro2;public class RealMovie implements Movie {@Overridepublic void play() {System.out.println("您正在观看的电影为:肖申克的救赎!");}}
  • Cinema 就是 Proxy 代理对象,它有一个 play() 方法。不过调用 play() 方法时,它进行了一些相关利益的处理,那就是广告。现在,我们编写测试代码。
package com.pro2;public class Cinema implements Movie {RealMovie realMovie;public Cinema(RealMovie realMovie) {super();this.realMovie = realMovie;}@Overridepublic void play() {guanggao(true);realMovie.play();guanggao(false);}public void guanggao(boolean isStart) {if (isStart) {System.out.println("电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!");} else {System.out.println("电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!");}}}
  • 测试代码
package com.pro2;public class ProxyTest {public static void main(String[] args) {RealMovie realmovie = new RealMovie();Movie movie = new Cinema(realmovie);movie.play();}
}
  • 输出结果:

动态代理

  • 既然是代理,那么它与静态代理的功能与目的是没有区别的,唯一有区别的就是动态与静态的差别。
  • 那么在动态代理的中这个动态体现在什么地方?
    上一节代码中 Cinema 类是代理,我们需要手动编写代码让 Cinema 实现 Movie 接口,而在动态代理中,我们可以让程序在运行的时候自动在内存中创建一个实现 Movie 接口的代理,而不需要去定义 Cinema 这个类。这就是它被称为动态的原因。
  • 示例:假设有一个大商场,商场有很多的柜台,有一个柜台卖茅台酒。我们进行代码的模拟。
  • 卖酒的一个接口
package com.pro3;public interface SellWine {void sellwine();}
  • 实现接口,卖茅台酒
package com.pro3;public class MaotaiJiu implements SellWine{public void sellwine() {System.out.println("我卖的是茅台酒!");}}
  • 代理可对其内容做修改和补充
package com.pro3;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {SellWine a1 = new MaotaiJiu();// 可以创建动态代理SellWine a2 = (SellWine)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class<?>[] {SellWine.class}, new InvocationHandler() {// 拦截所代理的类的行为@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("动态代理可添加,在卖酒动作前");// a1.sellwine();method.invoke(a1, args);System.out.println("动态代理可添加,在卖酒动作后");return null;}});a2.sellwine();}}
  • 语法
  • Proxy
/*
loader 自然是类加载器,一般写作:Thread.currentThread().getContextClassLoader()
interfaces 代码要用来代理的接口
h 一个 InvocationHandler 对象
*/
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  • InvocationHandler类
    InvocationHandler 是一个接口,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。
public interface InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}
  • invoke() 方法

数据库连接池(使用动态代理)

package com.situ.chapter5;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;/*** 数据库连接池* */
public class ConnectionPool {private static final String MYSQL_DRIVER = "com.mysql.cj.jdbc.Driver";private final String driver;private final String url;private final String username;private final String password;private final int initialSize;// 初始化连接数private int maxConnections = 15;// 最大连接数private List<PooledConnection> connections = new ArrayList<>();// 存储所有数据库连接public List<PooledConnection> getConnections() {return connections;}public ConnectionPool(String driver, String url, String username, String password, int initialSize) {super();this.driver = driver;this.url = url;this.username = username;this.password = password;this.initialSize = initialSize;// 初始化连接池initPool();}public ConnectionPool(String url, String username, String password, int initialSize) {this(MYSQL_DRIVER, url, username, password, initialSize);}public int getMaxConnections() {return maxConnections;}public void setMaxConnections(int maxConnections) {this.maxConnections = maxConnections;}/*** 初始化连接池*/private void initPool() {for (int i = 0; i < initialSize; i++) {// 原始连接Connection conn = buildConnection();// 池连接PooledConnection pc = new PooledConnection();// 创建代理conn = buildConnectionProxy(pc);pc.setConnection(conn);// 存储连接的代理实例connections.add(pc);}}/*** 创建数据库连接* * @return*/private Connection buildConnection() {try {Class.forName(driver);return DriverManager.getConnection(url, username, password);} catch (Exception e) {throw new RuntimeException("获取数据库连接失败,请确认后再试,或联系管理员", e);}}/*** 对某一个连接创建对应的代理* * @param conn* @return*/private Connection buildConnectionProxy(PooledConnection pc) {Connection result = (Connection)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class<?>[] {Connection.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("close")) {pc.setUsed(false);// 表示释放,不再使用return null;} else {return method.invoke(pc.getConnection(), args);}}});return result;}/*** 获取数据库连接* * @return*/public Connection getConnection() {for (PooledConnection pc : connections) {if (!pc.isUsed()) {pc.setUsed(true);// 设置成使用状态return pc.getConnection();}}if (connections.size() < this.maxConnections) {Connection conn = buildConnection();PooledConnection pc = new PooledConnection();conn = buildConnectionProxy(pc);pc.setConnection(conn);connections.add(pc);pc.setUsed(true);return pc.getConnection();}throw new RuntimeException("连接池已用完");}/*** 维护一个是否使用状态的连接* * @author snow1k* @date 2022/04/06*/public static class PooledConnection {private Connection connection;private boolean used = false;public boolean isUsed() {return used;}public void setUsed(boolean used) {this.used = used;}public Connection getConnection() {return connection;}public void setConnection(Connection connection) {this.connection = connection;}}
}

java基础 day-17 设计模式(单例,工厂,代理),静态动态代理,数据库连接池(动态代理)相关推荐

  1. java基础—多线程下的单例设计模式的安全问题

    //多线程下的单例设计模式 class Sing {//饿汉式不存在安全问题,因为其不是线程同步的private static Sing s = new Sing();private Sing(){} ...

  2. 25天掌握java基础(八)——static、单例、代码块、继承

    文章目录 Demo08-static.单例.代码块.继承 1.static 1.1static静态关键字 1.1.1static修饰成员变量 1.1.2static修饰成员方法 1.1.3static ...

  3. Java中的程序设计模式--单例与多例

    单例设计模式: 就是指一个类只允许产生一个实例化对象. 分析: 要想只能产生一个实例化对象,就意味着使用者不能在外部使用 new 生成一个实例,即表示该类的构造函数是私有的(貌似C++当中没有私有的构 ...

  4. 【Java】day9--main方法、单例设计模式、继承、方法重写部分知识点总结

    (一)main方法 jvm调用main方法,jvm也是一个程序     main方法详解:         public:公共  保证该类在任何情况下,jvm都对其方法可见.         stat ...

  5. java设计模式 单例_java设计模式一(单例模式singleton)

    1 概述 如果要保证系统里一个类最多只能存在一个实例时,我们就需要单例模式.这种情况在我们应用中经常碰到,例如缓存池.数据库连接池.线程池.一些应用服务实例等.在多线程环境中为了保证实例的唯一性其实并 ...

  6. spring中的单例工厂SingletonBeanRegistry设计与实现

    单例工厂接口为SingletonBeanRegistry,主要是单例的注册,其默认实现为DefaultSingletonBeanRegistry 1.类层次图 2.单例工厂在循环依赖时的流程

  7. 高仿真的类-单例工厂的顶层设计

    /*** 单例工厂的顶层设计*/ public interface V1BeanFactory {/*** 根据beanName从IOC容器中获得一个实例Bean* @param beanName* ...

  8. Java基础笔记 – 枚举类型的使用介绍和静态导入

    Java基础笔记 – 枚举类型的使用介绍和静态导入 本文由 arthinking 发表于404 天前 ⁄ Java基础 ⁄ 暂无评论 ⁄ 被围观 1,433 views+ 1.枚举(Enum): JD ...

  9. JAVA设计模式 - 单例与工厂模式

    前言 设计模式是在前人总结下 , 得出的经验, 设计模式的本质是面向对象设计原则的实际运用,是对类的封装性.继承性和多态性以及类的关联关系和组合关系的充分理解, 接着我们来看设计模式中的两种比较重要的 ...

  10. java static是单例_JAVA基础-static关键字及单例设计模式

    static关键字 基本概念使用static关键字修饰成员变量表示静态的含义, 此时成员变量由对象层级提升为类层级, 也就是整个类只有一份并被所有对象共享. 该成员变量随着类的加载准备就绪, 与是否创 ...

最新文章

  1. golang 实现 while 和 do……while 循环
  2. 中山大学新华学院c语言试题,中山大学新华学院国际学院2019级学生入学测试
  3. 通过完整示例来理解如何使用 epoll
  4. Apk去签名校验详解
  5. 设计模式学习笔记——外观(Facade)模式
  6. 10php1c,PHP程序员,进阶选择C还是C++亦或者别语言
  7. linux PHY驱动
  8. 几篇关于【核心网】MME、PGW、SGW和PCRF的介绍
  9. C++设计模式--观察员
  10. Could not find acceptable representation
  11. JavaEE 支付宝支付
  12. leancloud 怎么绑定域名_云引擎支持绑定加速域名 | LeanCloud 八月变化
  13. 图像处理中的差分求导计算和相应的卷积核(filter)
  14. win10系统无法登录ftp服务器失败,win10电脑下ftp连接失败怎么解决
  15. rtmp协议 java_rtmp协议详解 (一) handshake
  16. 华为 MA5683T GPON简单业务配置
  17. Exif信息 处理图片上传时翻转问题
  18. js正则表达式判断非负数和是否为网址
  19. 优矿-获取商品期权数据
  20. background-clip:从box-sizing:border-box属性入手,来了解盒模型

热门文章

  1. 用java求两个数的最大公因数_Java求两个数的最大公约数及最小公倍数、求多个数的最大公约数及最小公倍数...
  2. win7旗舰版升级win10
  3. AntDsign菜单高亮
  4. 统计学的Python实现-015:调和平均数
  5. 在Google上做搜索引擎优化 (SEO),最重要的是哪几点?
  6. CTFSHOW 愚人节欢乐赛WP
  7. mysql让局域网访问权限_mysql 设置局域网内可访问
  8. 可以实现psd转png转换器有哪些?这些工具能让你轻松转换图片格式
  9. Granger格兰杰因果关系的设计、基本假设和额外要求
  10. TOEFL 9个托福独立写作模板总结