设计模式-工厂模式/代理模式

2023-05-16

工厂模式

创建对象时不会对客户端暴露创建逻辑,并且通过使用一个共同的接口来指向新创建的对象,实现创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂,Spring中的IOC容器创建bean的过程就是用了工厂模式,容器中有个静态的Map集合存储对象,为了让每个对象只生产一次,让工厂符合单例模式。定义一个创建对象的接口,让其子类决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行

优点:

  • 工厂模式是最常用的实例化对象模式,工厂方法代替new操作的一种模式
  • 降低程序的耦合性
  • 将选择实现类、创建对象统一管理控制,将调用者和实现类解耦
简单工厂模式(静态工厂)

相当于一个工厂中有各种产品,客户无需知道产品名称,只需要知道产品类对应的参数,但是工厂的职责过重,而且类型过多时,不利于系统扩展维护,实质是工厂类根据传入的参数动态决定创建哪一个产品类(这些产品类继承一个父类,或实现一个接口)

package com.clay.factory;
public interface Phone {
    void run();
}

//产品类 都是实现一个接口
package com.clay.factory;
public class Honor implements Phone{
    @Override
    public void run() {
        System.out.println("Honor");
    }
}

package com.clay.factory;
public class Oppo implements Phone{
    @Override
    public void run() {
        System.out.println("OPPO");
    }
}

package com.clay.factory;
public class Vivo implements Phone{
    @Override
    public void run() {
        System.out.println("VIVO");
    }
}

// 静态工厂类
package com.clay.factory;

public class PhoneFactory {
    public static Phone create(String type){
        if(type == null){
            return null;
        }
        if(type.equals("Vivo")){
            return new Vivo();
        }else if(type.equals("Honor")){
            return new Honor();
        }else if(type.equals("Oppo")){
            return new Oppo();
        }
        return null;
    }
}

// 测试
package com.clay.factory;
public class PhoneTest {
    public static void main(String[] args) {
        Phone vivo = PhoneFactory.create("Vivo");
        Phone honor = PhoneFactory.create("Honor");
        Phone oppo = PhoneFactory.create("Oppo");
        vivo.run();
        honor.run();
        oppo.run();
    }
}
工厂方法模式

此模式的核心是封装类中变化大部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和后期维护扩展的目的。

又称为**多态性工厂模式,工厂类不再负责所有产品的创建,而是具体的创建交给子类去做。**该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

// 产品类和工厂类依然是简单工厂的示例代码

// 工厂方法调用接口
public interface PhoneFactory {
    Phone create();
}

// 创建工厂方法调用接口的实例
public class OppoFactory implements PhoneFactory{
    @Override
    public Phone create() {
        return new Oppo();
    }
}

public class HonorFactory implements PhoneFactory{
    @Override
    public Phone create() {
        return new Honor();
    }
}

public class VivoFactory implements PhoneFactory{
    @Override
    public Phone create() {
        return new Vivo();
    }
}

//测试
public static void main(String[] args) {
        Phone vivo = new VivoFactory().create();
        Phone oppo = new OppoFactory().create();
        Phone honor = new HonorFactory().create();
        vivo.run();
        oppo.run();
        honor.run();
    }
抽象工厂模式

抽象工厂是工厂的工厂,抽象工厂可以具体创建工厂,由具体工厂来创建具体产品

package com.clay.factory.abstractfac;

// 手机工厂
public interface PhoneFactory {
    Camera createCamera(String type);
    Screen createScreen(String type);

}

// 摄像头工厂
class CameraFactory implements PhoneFactory{

    @Override
    public Camera createCamera(String type) {
        if(type.equals("CameraA")){
            return new CameraA();
        }else if(type.equals("CameraB")){
            return new CameraB();
        }
        return null;
    }

    @Override
    public Screen createScreen(String type) {
        return null;
    }
}

// 屏幕工厂
class ScreenFactory implements PhoneFactory{

    @Override
    public Camera createCamera(String type) {
        return null;
    }

    @Override
    public Screen createScreen(String type) {
        if(type.equals("ScreenA")){
            return new ScreenA();
        }else if(type.equals("ScreenB")){
            return new ScreenB();
        }
        return null;
    }
}
// 选择工厂
class PhoneCreateFactory{
    public static PhoneFactory getFactory(String factory){
        if(factory.equals("Camera")){
            return new CameraFactory();
        }else if(factory.equals("Screen")){
            return new ScreenFactory();
        }
        return null;
    }
}

代理模式

**为其他对象提供一种代理以控制对这个对象的访问。**代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标之间起到中介的作用。代理再原有代码乃至原业务不变的情况下,直接再业务流程中切入新代码。应用场景Spring AOP、日志打印、异常处理等

分类

静态代理:静态代理模式

动态代理(jdk):使用反射完成代理,不能直接代理类,需要有顶层接口才能使用,常见是Mybatis的mapper文件代理。

静态代理

程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了,通常代理类和委托类会实现同一接口或者派生自相同父类

public interface Subject {
    void request();
}
// 真实主题
public class RealSubject implements Subject{
    @Override
    public void request() {
        System.out.println("访问真实的主题");
    }
}

// 代理 ,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。
public class Proxy implements Subject{

    private RealSubject realSubject;

    @Override
    public void request() {
        if(realSubject == null){
            realSubject = new RealSubject();
        }

        preRequest();
        realSubject.request();
        postRequest();
    }

    public void preRequest(){
        System.out.println("访问真实主题之前的操作");
    }

    public void postRequest(){
        System.out.println("访问真实主题之后的操作");
    }
}

缺点是每个需要代理的对象都要自己重复编写代理,如果被代理类增加了方法,代理类就要同步增加,不符合开闭原则。

动态代理

使用反射动态创建,利用JDK的API动态的在内存中构建代理对象,能在代码运行时动态改变某个对象的代理,并且能为代理对象动态增加方法,增加行为。必须是面向接口的,目标业务类要实现接口。

public interface Subject {
    void request();
}

public class RealSubject implements Subject{
    @Override
    public void request() {
        System.out.println("访问真实的主题");
    }
}

public class InvocationHandlerImpl implements InvocationHandler {
    private Object target;

    public InvocationHandlerImpl(Object target){
        this.target = target;
    }

    // 动态代理实际运行的代理方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用之前处理");
        // 反射创建对象,args是构成方法的参数
        Object invoke = method.invoke(target, args);
        System.out.println("调用之后处理");

        return invoke;
    }

}
public class Test {

    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(realSubject);
        // 获取类加载器
        ClassLoader classLoader = realSubject.getClass().getClassLoader();
        // 获取接口
        Class<?>[] interfaces = realSubject.getClass().getInterfaces();

        Subject subject =(Subject) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        subject.request();
    }
}

参考

菜鸟教程(https://www.runoob.com/design-pattern/singleton-pattern.html)

博客https://blog.csdn.net/weixin_43122090/article/details/105462226

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式-工厂模式/代理模式 的相关文章

  • VS报错——无法打开文件XXX.lib

    添加lib文件 xff1a 配置属性 gt 链接器 gt 输入 gt 附加依赖项加入库名 xff08 lib xff09 xff1b 或者是在cpp源文件中用 pragma comment lib lib 来代替 此时编译会提示 xff1a
  • Kafka与Flink结合使用

    Kafka与Flink结合使用 本地连接kafka 首先可以先以本地模式来对kafka进行操作 当我们在系统 xff08 可以是windows xff0c 尽量linux xff09 上部署好了Zookeeper和kafka集群 xff0c
  • 当前脑电入门

    资料 1 公众号脑机接口社区汇总 2 MNE 3 EEG科普 4 公众号BrainTechnology 5 公众号路同学 6 知乎Alex 7 程序员大本营 xff0c 很多相关 数据集 上海交大SEED数据集 BCI EEG数据集 xff
  • 使用Diskspd测试SQL Server存储子系统

    In this article we will learn how to test our storage subsystems performance using Diskspd The storage subsystem is one
  • Python读取mat文件——matlab的数据

    Python处理mat文件 1 读取2 数据格式 1 读取 很多人使用MATLAB并将数据存储在 mat文件中 这些文件是什么 这些文件包含MATLAB工作空间分配给它们的变量和对象列表 它作为字典导入到Python中 xff0c 其中键是
  • 我的毕设4.24—

    EEG 1 寻找数据2 读入数据3 了解数据3 处理数据 1 寻找数据 要找到关于情感的EEG数据集 by CSDN 2 读入数据 因为获取的数据集是mat文件 xff0c 解决Python读取mat文件 by 文本检索图书馆w pytho
  • 关于提高信息传输率三个方法之一——增加频带宽度

    转载原作 以下解释为什么增加频带宽度可减弱码间串扰 主要由于高频信号分量对波形影响是变得接近数字信号 xff0c 分界垂直 xff0c 减小斜坡 信道极限容量 任何实际的信道都不是理想的 xff0c 在传输信号时会产生各种失真以及带来多种干
  • CSMA/CD计算机网络(第七版)谢希仁 3-25 CSMA/CD

    计算机网络 xff08 第七版 xff09 谢希仁 3 25 假定站点A和B在同一个10Mb s以太网网段上 这两个站点之间的传播时延为225比特时间 站点A和B在t 61 0时同时发送了数据帧 当t 61 225比特时间 xff0c A和
  • L3-019 代码排版 (30 分) 别看 没改完

    太复杂了啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 不做了 include lt iostream gt include lt cstdio gt using namespace std string s bo
  • 无人机航线规划

    非最短非最长 xff0c 因为只有10个点 xff0c 直接搜 标题 xff1a 无人机航线规划 某海岛遭遇飓风灾害 xff0c 道路设施受损严重 救援部门为尽快探明主要交通干道的受损情况 xff0c 在地图上划定了主要交通干道的侦察点 x
  • 17蓝桥C语言B组 7.日期问题

    标题 xff1a 日期问题 小明正在整理一批历史文献 这些历史文献中出现了很多日期 小明知道这些日期都在1960年1月1日至2059年12月31日 令小明头疼的是 xff0c 这些日期采用的格式非常不统一 xff0c 有采用年 月 日的 x
  • 安装Scipy。。。。。。。。

    放弃pip转用conda戳 2019 4 21 安装Scipy 以下所有安装过程假设电脑中安装有pip xff0c 如果没有就请装一个 首先 xff0c windows正常通过pip命令安装numpy和scipy的时候 xff1a pip
  • 《Python编程:从入门到实践》文件资料下载

    感谢分享者 下载地址 往下翻 下载压缩包
  • 01、BUCK电路的参数计算

    案例 xff1a 设计一个Buck电路 xff0c 满足如下性能指标要求 xff1a 一 性能指标要求 1 输入电压 2 输出电压 3 输出电压纹波 4 电流纹波 5 开关频率 二 需要计算的参数 三 BUCK电路拓扑 四 BUCK电路工作
  • mysql分页是物理分页_学习MySQL:什么是分页

    mysql分页是物理分页 In this article I am going to explain that in MySQL what is pagination and how we can implement it When we
  • Ubuntu下嵌入式arm板Qt环境搭建

    参考 xff1a https blog csdn net lpp0900320123 article details 24876159 系统环境 xff1a 主机操作系统 xff1a ubuntu14 04 主机编译器 xff1a gcc4
  • FreeRDP在windows上的编译和使用

    FreeRDP 是 Windows下远程桌面协议 xff08 RDP xff09 的一种实现 xff0c 类似于微软自带的mstsc xff0c 可以实现windows上的远程连接 xff0c 特别是对于在ubuntu或者在Mac下 xff
  • Ubuntu-GPU

    查看CUDA的版本 xff1a nvcc V 显示GPU的信息 xff1a nvidia smi 查看GPU的运行 xff1a xff08 每 0 1s 显示一次显存的情况 xff09 watch n 0 1 nvidia smi
  • 面向对象程序设计语言和面向过程程序设计

    面向对象程序设计语言和面向过程程序设计语言的区别由哪些 xff1f 面向对象的特点是 xff1a 封装 xff0c 继承 xff0c 多态 xff0c 其中多态又分为重载和重写 xff0c 面向对象的编程思想更接近现实的事物 面向对象的优点
  • Anaconda安装在D盘后无法在CMD窗口执行python命令

    Anaconda安装在D盘后无法在CMD窗口执行python命令以及库的安装办法 解决办法 xff1a 1 添加环境变量 我的电脑 右键属性 高级系统设置 环境变量 双击变量PATH 将Anaconda和Scripts的路径加入即可 xff

随机推荐

  • Ubuntu18.04配置多用户远程桌面控制display 0问题解决

    Ubuntu18 04配置xrdp多用户远程桌面控制 display 0问题解决 找了网上的所有方法都没有解决 xff0c 重新安装xrdp好了一会儿还会出现display 0情况 xff0c 偶然一次配置了ssh xff0c 然后就好了
  • Windows后台运行并启动Frpc客户端界面

    Windows后台运行并启动Frpc客户端界面 frp搭建内网穿透可以看我另外一篇 1 frps服务端配置 common bind port 61 3000 vhost http port 61 4000 vhost https port
  • 树莓派4安装Debian10

    原因 虽然树莓派自家的Raspberry Pi OS也是Debian10 xff0c 但是作为有些强迫症的程序员 xff0c 我还是选择安装官方发布的Debian10 其实安装很简单 xff0c 直接写入内存卡就行了 xff0c 但是不能s
  • Framework中的连接管理机制--4G和wifi之间的切换流程(转)

    https blog csdn net u010961631 article details 48629601 上一节 Wifi服务框架介绍 介绍了WIFI的大致框架 xff0c 本文主要介绍连接管理中的几个重要角色 xff0c 包括 xf
  • pandas学习笔记:pandas.Dataframe.rename()函数用法

    pandas学习笔记 xff1a pandas Dataframe rename 函数用法 pandas Dataframe rename 函数主要是用来修改Dataframe数据的行名和列名 主要用到的参数有 columns xff1a
  • mac os 查看日历_从命令行查看Mac日历

    mac os 查看日历 As someone that loves using UI tools I do pride myself in learning how to accomplish the same feats from com
  • Sql基础教程

    sql基础教程 第一章 数据库与sql1 1 数据库是什么DBMS的种类 1 2 数据库的结构表的结构 1 3 SQL 概要SQL语句及其种类SQL的基本书写规则 1 4 表的创建数据库的创建表的创建命名规则数据类型约束的设置 1 5 表的
  • Jetson TX2更换软件源(转)

    感谢博客 xff1a 点击打开链接 TX2的软件源为国外服务器 xff0c 网速会很慢 xff0c 需要换国内的ARM源 1 备份 etc lib路径下的source list文件 xff0c 然后在终端 xff08 按ctrl 43 al
  • c语言中求数组长度(*的作用,定义指针变量与取值)

    最近在学习c语言 xff0c 在c语言中少了很多库函数 xff0c 就比如我在求数组长度的时候 xff0c len 不能用了 xff0c 这在python中是自带的函数 即使在c 43 43 中 xff0c 求字符串长度时也能用str le
  • 个人使用ubuntu18相关配置

    root登陆 1 首先获得临时的root权限 xff0c 因为后面的一些操作需要root权限才可以 xff0c 打开终端输入以下命令 sudo s 之后直接输入当前账户的密码 xff0c 就可以获得临时的root权限 2 先创建root账户
  • Manjaro内存不足解决记录

    1 Linux虚拟机 最近在家闲得没事做 xff0c 就使用VMware装了一个linux虚拟机 xff0c 虽然之前装过许多linux发行版的虚拟机 xff0c 也装过win10 43 Deepin双系统 xff0c 但是从来没具体了解过
  • String/StringBuilder/StringBuffer

    String StringBuilder StringBuffer 1 可变性 String 字符串常量 xff0c 字符串是不可变的 源码中 xff1a span class token keyword private span span
  • 计算机网络-网络结构

    计算机网络 三种网络结构 OSI xff1a 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 TCP IP xff1a 网络接口层 网际层 传输层 应用层 五层 xff1a 物理层 数据链路层 网络层 传输层 应用层 应用层 它
  • 计算机网络-三次握手/四次挥手/可靠传输/ARQ协议

    计算机网络 TCP三次握手 同步SYN 确认ACK 发送端 SYN标志的数据报 seq 61 x gt 接收端 xff08 SYN 61 1 xff09 发送端 lt SYN ACK标志的数据报 seq 61 y ack 61 x 43 1
  • 计算机网络-拥塞控制/HTTP/URL

    滑动窗口和流量控制 TCP利用滑动窗口实现流量控制 xff0c 流量控制就是为了控制发送方发送速率 xff0c 保证接收方来得及接收 接收方发送的确认报文中的窗口字段可以来控制发送方窗口大小 xff0c 从而影响发送方的发送速率 xff0c
  • Integer和int进行==比较

    Integer amp int int是Java的基本数据类型 xff0c 而Integer是它的包装类 xff0c 61 61 在进行比较时 xff0c 如果是基本类型 xff0c 比较的是值 xff0c 如果是引用类型 xff0c 比较
  • deepin恢复出厂设置_如何恢复出厂设置

    deepin恢复出厂设置 There comes a time in every user s life when they have to reset something back to its factory default Perha
  • JUC-JMM/Volatile/单例模式

    JMM Java内存模型 xff0c 是一个概念 xff0c 不存在的东西 xff0c 概念 约定 关于JMM的一些同步约定 xff1a 线程解锁前 xff0c 必须把共享变量刷回主存线程加锁前 xff0c 必须读取主存中的最新值到工作内存
  • 设计模式-六大原则/单例模式

    设计模式 概念 xff1a 是一套被反复使用 多数人知晓的 经过分类编目的 代码设计经验的总结 作用 xff1a 为了可重用代码 让代码更容易被他人理解 保证代码可靠性 程序的重用性 JDK Spring等源码中许多地方用到了设计模式 设计
  • 设计模式-工厂模式/代理模式

    工厂模式 创建对象时不会对客户端暴露创建逻辑 xff0c 并且通过使用一个共同的接口来指向新创建的对象 xff0c 实现创建者和调用者分离 xff0c 工厂模式分为简单工厂 工厂方法 抽象工厂 xff0c Spring中的IOC容器创建be