Java设计模式-单例/工厂/代理

news/2024/11/30 2:25:43/

设计模式

    • 单例模式
      • 实现
      • 饿汉式
      • 懒汉式
      • 双重检测
    • 工厂模式
      • 简单工厂模式
      • 抽象工厂
    • 代理模式
      • 静态代理
      • 动态代理
        • JDK动态代理原理
        • cglib代理原理

单例模式

单例模式用来保证类在内存中只能有一个对象,因为对象的创建和销毁都会占用系统资源,一些昂贵的资源可以使用单例模式,节省系统资源

特点

  • 单例类只能有一个实例。
  • 单例的类只能自己创建自己的实例。
  • 单例类必须能够提供自己的唯一实例给其他类

使用场景

  • Spring中的bean使用到了单例模式
  • 计数器使用到了单例模式
  • servlet也是一个单例模式

实现

  • 提供一个本类的唯一实例
  • 私有化构造,防止外界随意创建本类的实例
  • 提供一个公开的静态的方法来让外界获取本类的唯一实例

饿汉式

饿汉式单例模式就是在类加载的时候就立即初始化,并且创建单例对象。不管你有没有用到,都先建好了再说。它绝对线程安全,在线程还没出现以前就实例化了,不可能存在访问安全问题。
优点:线程安全,没有加任何锁、执行效率比较高。
缺点:类加载的时候就初始化,不管后期用不用都占着空间,浪费了内存。
在这里插入图片描述

懒汉式

懒汉式,顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则直接返回,没有则新建。

在这里插入图片描述

双重检测

兼顾性能和线程安全问题

public class Singleton{// 提供一个本类的唯一实例 ,volatile 锁private volatile static final Singleton instance = null;// 私有化构造,防止外界随意创建本类的实例private Singleton(){}// 提供一个公开的静态的方法来让外界获取本类的唯一实例public static getInstance(){if(instance == null){// 锁住临界资源synchronized(Singleton.class){instance = instance == null ? instance = new Singleton() : instance;}}return instance;}
}

工厂模式

定义一个用于创建对象的接口,然子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
工厂模式有一个工厂类,工厂类知道产品类的具体实现细节,并决定何时实例化哪一个类。

简单工厂模式

简单工厂模式:又称为静态工厂方法模式,它属于类创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个工厂类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

有一个父类,这个父类有多个子类,还有一个工厂类,工厂类中创建了父类对象,但是没有实例化,要用到对象的时候,根据传进来的参数不同,选择实例化不同的子类

public interface IVersion {void test();
}public class UserDao1 implements IVersion{@Overridepublic void test() {System.out.println("version1...");}
}public class UserDao2 implements IVersion{@Overridepublic void test() {System.out.println("version2...");}
}public class UserDao3 implements IVersion{@Overridepublic void test() {System.out.println("version3...");}
}/**工厂类**/
public class MyFactory {/*** 声明常量代替版本号*/public final static int V_ONE = 1;public final static int V_TWO = 2;public final static int V_THREE = 3;/*** 创建公开的静态方法* @return*/public static IVersion getInstance(Integer version){IVersion userDao = null;switch (version){case V_ONE:userDao = new UserDao1();break;case V_TWO:userDao = new UserDao2();break;case V_THREE:userDao = new UserDao3();break;default:System.out.println("简单工厂模式");}return userDao;}
}

抽象工厂

工厂方法模式针对的是一个产品等级结构;
而抽象工厂模式则是针对的多个不同产品等级结构。
或者话,普通工厂模式只能生产具体某一类产品。但是抽象工厂,可以生产多个不同类的产品。打破了工厂与产品之间一对一的关系。
要添加新的大类,就要修改工厂类,违反了开闭原则。

①创建鼠标类的共同接口
//鼠标的接口
interface mouse {public void show();
}②创建戴尔鼠标类实现鼠标接口,即具体的产品类
//具体的产品类(戴尔鼠标),来实现鼠标这个抽象接口
class Dellmouse implements mouse {public void show() {System.out.println("这是个戴尔鼠标");}
}③创建惠普鼠标类来实现鼠标接口,即具体的产品类
//具体的产品类(惠普鼠标),来实现鼠标这个抽象接口
class Hpmouse implements mouse {public void show() {System.out.println("这是个惠普鼠标");}
}④创建键盘类的共同接口
//键盘的接口
interface keyboard {public void show();
}⑤创建戴尔键盘类来实现键盘接口,即具体的产品类
//具体的产品类(戴尔键盘),来实现键盘这个抽象接口
class Dellkeyboard implements keyboard {public void show() {System.out.println("这是个戴尔键盘");}
}⑥创建惠普键盘类来实现键盘接口,即具体的产品类
//具体的产品类(惠普键盘),来实现键盘这个抽象接口
class Hpkeyboard implements keyboard {public void show() {System.out.println("这是个惠普键盘");}
}⑦创建抽象工厂类共同接口
//抽象工厂类接口
interface PCFactory {public mouse createmouse();public keyboard createkeyb();
}⑧创建具体工厂类A,来实现抽象工厂类接口
//具体工厂类A,来实现抽象工厂类接口class FactoryA implements PCFactory {public mouse createmouse() {     //实现接口的方法return new Dellmouse();       //返回创建具体产品类1}public keyboard createkeyb() {    //实现接口的方法return new Dellkeyboard();   //返回创建具体产品类2}
}⑨创建具体工厂类B,来实现抽象工厂类接口
//具体工厂类B,来实现抽象工厂类接口
class FactoryB implements PCFactory {public mouse createmouse() {   //实现抽象接口方法return new Hpmouse();      //返回创建具体类}public keyboard createkeyb() {   //实现抽象接口方法return new Hpkeyboard();    //返回创建具体类}
}⑩用户端的调用
//用户端的调用
public class user {public static void main(String[] args) {PCFactory f=new FactoryA();  f.createmouse().show();  //用户类只跟接口打交道,只需调用接口的方法f.createkeyb().show();PCFactory ff=new FactoryB();ff.createmouse().show();ff.createkeyb().show();}
}

代理模式

代理模式简单的说就是可以在不改变原来代码的情况下,通过引入代理类来扩展功能

静态代理

比如我们有一个接口角色:增删改查业务, 然后有一个实现类去完成这些具体的实现。
现在我们需要为它增加日志功能,
我们先写一个代理类去继承接口,然后在里面加上增删改查的实现类对象。然后再用对象调用方法,再在方法里加上新的功能。

  1. 创建一个抽象角色,比如咋们平时做的用户业务,抽象起来就是增删改查!
//抽象角色:增删改查业务
public interface UserService {void add();void delete();void update();void query();
}
  1. 我们需要一个真实对象来完成这些增删改查操作
//真实对象,完成增删改查操作的人
public class UserServiceImpl implements UserService {public void add() {System.out.println("增加了一个用户");}public void delete() {System.out.println("删除了一个用户");}public void update() {System.out.println("更新了一个用户");}public void query() {System.out.println("查询了一个用户");}
}
  1. 需求来了,现在我们需要增加一个日志功能,怎么实现!
  • 思路1 :在实现类上增加代码 【麻烦!】
  • 思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!
  1. 设置一个代理类来处理日志! 代理角色
//代理角色,在这里面增加日志的实现
public class UserServiceProxy implements UserService {private UserServiceImpl userService;public void setUserService(UserServiceImpl userService) {this.userService = userService;}public void add() {log("add");userService.add();}public void delete() {log("delete");userService.delete();}public void update() {log("update");userService.update();}

动态代理

  • 动态代理的角色和静态代理的一样 .
  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
    基于接口的动态代理----JDK动态代理
    基于类的动态代理–cglib

JDK的动态代理只能用来代理接口,
而CGLIB的动态代理既可以代理接口也可以用来代理

JDK动态代理原理

JDK动态代理的核心是InvocationHandler接口和Proxy类,如果代理的类没有实现InvocationHandler接口时,就会使用CGLIB代理

原理:
通过一个代理类区实现InvocationHandler接口,去实现接口的invoke方法,这个方法有三个参数(类,方法,参数),然后通过反射来调用

//这是接口
public interface A{void hello();}
//这是接口实现类
public class B implements A{
@override
void hello()hello
)}//JDK动态代理过程
代理类implements InvocationHandler{
invoke(proxy , method , argsX){//类 ,方法, 参数
//代理开始method.invoke( target , args); //要代理的对象, 参数
//代理结束}
}

cglib代理原理

cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final。

原理:待续


http://www.ppmy.cn/news/535195.html

相关文章

惠普涉嫌做局压货 代理商400万货砸在手里

惠普渠道生意伙伴北京烽火九州科技有限公司称,被惠普“耍”了一通,面临400多万元的损失。 惠普中国发言人陈雷昨日对外表示,正展开彻底调查,将在合适时候给予回应。 “当初我想,有惠普三个业务部门的老大邮件确认&am…

惠普服务器F10中收集硬件日志方法

HPE惠普服务器F10中收集硬件日志方法 (2018-08-04 22:55:26) 转载▼ 分类: 贵阳惠普服务器总代理 步骤:(下面这个截图是我之前截的,界面可能会有细微出入.但是方法都一样.) 先把u盘插入到服务器上. 重启服务器点击f10,如果屏幕有3个选项,选择第一个intelligent …

Java常见设计模式之代理模式

指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其它相关业务的处理。比如生活中的通过代理访问网络,客户通过网络代理连接网络(具体业务),由代理服务器完成用户权限和访问限制…

GEE:欧几里得距离——计算目标图像中每个像素到目标像素的距离

作者:CSDN @ _养乐多_ 利用欧几里得距离计算目标图像中每个像素到目标像素的距离,以量化像素与目标的接近程度。 结果如下图所示, 文章目录 一、欧几里得距离简介二、代码一、欧几里得距离简介 欧几里得距离(Euclidean distance)是在数学中常用的一种距离度量方式,用于…

一文带你理解JDK动态代理原理

写在开头,为什么要写这篇文章。 为了面试的时候有话说,以及记录自己对动态代理的理解。 1.为什么要有动态代理? 动态代理可能在平时编程中很少看到,但是在使用的各种框架底层都使用了动态代理。它主要是对我们编写的代码逻辑进…

惠普渠道回归

2014财年,惠普企业集团业务获得了“意外”的快速增长。如何才能将这种“意外”增长变成持续、稳定的增长呢?惠普企业集团已经胸有成竹——强化风险管理,拓展行业和区域市场,投入过亿元资金支持渠道发展。 “2014财年是惠普企业集团业务稳步增…

设计模式——代理模式你真的了解了吗

代理模式 代理模式一、代理模式的简述二、代理模式的结构三、代理模式的实现四、JDK代理方式五、小结 代理模式 引入: 代理模式是常用的结构性模式之一,当无法直接访问某个对象或访问某个对象困难时,我们可以通过代理对象间接访问,为了保证…

Geocomputation (4)geometry operations

Geocomputation (4)geometry operations 来源:https://github.com/geocompx/geocompy 1.准备工作 #| echo: false import pandas as pd import matplotlib.pyplot as plt pd.options.display.max_rows = 6 pd.options.display.max_columns =