Android工厂模式

前言

工厂模式是创建型模式,使我们常用/常见的模式之一。多用于需要生成复杂对象的地方。用new就可以完成创建的对象就无需使用。工厂模式降低了对象之间的耦合度,由于工厂模式依赖抽象的架构,实例化的任务交由子类去完成,所以有很好的扩展性。

工厂模式

定义:一个用于创建对象的接口,让子类决定实例化哪个类
工厂模式一般也就两大类:
普通工厂模式:生产具体的产品,创建的产品是类(Class)。
抽象工厂模式:生产抽象的产品,创建的产品是接口(Interface)。
一开始你可能理解不上来,当你看完这篇文章,你理解了,其实他们并不复杂,我们先来看一个普通工厂的例子
(这里扩展一点,虽然普通工厂表面上创建的是抽象类,但java特性里抽象类是不能被实例化的。我没每次创建的时候,实际上是以匿名内部类的方式创建。实际是它继承并创建的一个新的类。所以它仅仅是一个普通工厂)

普通工厂模式举例

我们举一个生产Nokia手机的例子。

public abstract class NokiaPhone {public abstract void powerOnPhone();
}

先试定义了一个抽象类,抽象出方法powerOnPhone(),模拟手机开机的动作。(ps:抽象类作用简单点说就是抽象出一些方法,需要子类去实现,自己不能实现。起到一个抽象的作用)
然后我们定义具体的手机

public class Nokia5200 extends NokiaPhone {@Overridepublic void powerOnPhone() {Log.d("Factory","Nokia5200 power on");}
}public class NokiaN97 extends NokiaPhone{@Overridepublic void powerOnPhone() {Log.d("Factory","NokiaN97 power on");}
}

然后我们定义了具体的手机Nokia5200和NokiaN97两款手机。并实现了抽象方法powerOnPhone
现在产品定义好了,我们就要定义工厂了,首先我们也抽象出工厂的方法

public abstract class Factory {public abstract <T extends NokiaPhone> T createNokia(Class<T> clz);
}

工厂的方法无非就是生产手机,所以我们抽象出来了createNokia方法,现在我们来定义工厂

public class NokiaFactory extends Factory {@Overridepublic <T extends NokiaPhone> T createNokia(Class<T> clz) {NokiaPhone nokiaPhone = null;try {nokiaPhone = (NokiaPhone) Class.forName(clz.getName()).newInstance();} catch (Exception e) {e.printStackTrace();} return (T) nokiaPhone;}
}

NokiaFactory工厂也很简单就实现了抽象方法createNokia,来生产不同的手机。这里我们使用了反射方法

nokiaPhone = (NokiaPhone) Class.forName(clz.getName()).newInstance();

这句话的意思是通过类名(ClassName)来实例化具体的类,用的是反射机制来实现。
然后我们来看看我们怎么用工厂生产手机。

NokiaFactory nokiaFactory = new NokiaFactory();
Nokia5200 nokia5200 = nokiaFactory.createNokia(Nokia5200.class);
NokiaN97 nokiaN97 = nokiaFactory.createNokia(NokiaN97.class);

我们用工厂创建了两个手机,一个nokia5200,一个nokiaN97。然后我们开机试试

nokia5200.powerOnPhone();
nokiaN97.powerOnPhone();

看log

D/Factory: Nokia5200 power on
D/Factory: NokiaN97 power on

至此,一个工厂模式就写完了,可以看到工厂模式的代码结构其实很简单。有的读者可能会想为啥NokiaFactory为啥要用反射呢,其实用反射主要是为了代码简洁,如果不这么写,你可能像下面的代码这样写

// 方案一
public class NokiaFactoryNokia5200 extends Factory {@Overridepublic <T extends NokiaPhone> T createNokia() {Nokia5200 nokia5200 = new Nokia5200();return (T) nokia5200;}
}public class NokiaFactoryNokiaN97 extends Factory {@Overridepublic <T extends NokiaPhone> T createNokia() {NokiaN97 nokiaN97 = new NokiaN97();return (T) nokiaN97;}
}
// 方案二
public class NokiaFactory extends Factory {@Overridepublic <T extends NokiaPhone> T createNokia(Class<T> clz) {Log.d("Factory",clz.getSimpleName());if (clz.getSimpleName().equals("Nokia5200")) {Nokia5200 nokia5200 = new Nokia5200();return (T) nokia5200;} else if (clz.getSimpleName().equals("NokiaN97")) {NokiaN97 nokiaN97 = new NokiaN97();return (T) nokiaN97;}return null;}
}
普通工厂模式小结

1、上面两种方案,一是为每个手机单独创建一个工厂,或者通过带入的class来选择创建都能实现,但是如果手机型号过多,代码就显得很长,当然最好还是用反射的方法,这里只是为了进行一个说明。
2、上面NokiaFactoryNokia5200、NokiaFactoryNokiaN97这种情况也有适合用这种方式的地方。我们下面讲解抽象工厂的时候就会用不同工厂对应不同产品的方式来创建。并非一定是反射的方法。
3、最开始的例子还可以省略抽象方法,抽象方法只是为了更具体化,不过不建议这么做,抽象方法使我们的NokiaPhone更规范。代码可读性也更好。
4、普通工厂模的创建的产品是具体的类,这个例子的产品是NokiaPhone.class,虽然它是一个抽象类,但使用时已经创建的匿名内部类是一个具体的类。

抽象工厂模式例子

抽象工厂我们举例一个生产Iphone零件的例子。
我们先定义产品,这里是生产零件,我们定义两个抽象产品,一个CPU,一个电池。这里我把两个接口写在了一起,当然你也可以分开写成两个。

public interface component {public interface CPU {void showCpuName();}public interface Battery {void showBatteryCapacity();}
}

然后我们定义CPU的具体产品,一个A9,一个A10

public class A9 implements component.CPU {@Overridepublic void showCpuName() {Log.d("AbstractFactory","A9");}
}public class A10 implements component.CPU {@Overridepublic void showCpuName() {Log.d("AbstractFactory","A10");}
}

然后是两种电池产品,一个1000ma,一个1200ma

public class Battery1000ma implements component.Battery {@Overridepublic void showBatteryCapacity() {Log.d("AbstractFactory","battery is 1000ma");}
}
public class Battery1200ma implements component.Battery {@Overridepublic void showBatteryCapacity() {Log.d("AbstractFactory","battery is 1200ma");}
}

产品定义好了,我们来定义工厂了,依旧先用抽象类,抽象出工厂类的方法

public abstract class Factory {public abstract component.CPU createCPU();public abstract component.Battery createBattery();
}

注意一点这里的抽象方法跟抽象工厂模式并无实际关系,不是因为这里使用抽象类而因此叫抽象工厂模式,而是因为工厂模式生产的产品。一个是component.CPU,一个是component.Battery。他们两个都是接口,都是抽象出来的,抽象工厂模式因此而来。
虽然java特性里,抽象类和接口不都能实例化。都是创建匿名内部类方式来创建对象,但普通工厂创建的是抽象类,还是对象的一种描述,而抽象工厂思想上还是创建的接口。接口编程,由此特性所以它叫抽象工厂。
接着我们看具体工厂的实现,这里我们将用不同的工厂对应不同的产品来举例

public class IPhone6Factory extends Factory {@Overridepublic component.CPU createCPU() {return new A9();}@Overridepublic component.Battery createBattery() {return new Battery1000ma();}
}public class Iphone7Factory extends Factory {@Overridepublic component.CPU createCPU() {return new A10();}@Overridepublic component.Battery createBattery() {return new Battery1200ma();}
}

1、可以看到IPhone6Factory和Iphone7Factory两个工厂模式他们创建的产品相同,都是创建CPU和Battery这两个抽象产品。而这两个抽象产品又可以是同接口不同子类实例。

抽象工厂模式小结

1、抽象工厂模式创建的产品是接口,抽象出来的。
2、上面的例子其实跟普通工厂模式例子没太大的差别,除了产品不同,实现的思想都是一样的,只是这里用了不同的工厂对应不同的产品。普通工厂模式也可以这样用。
3、抽象工厂有一个显著的优点是分离接口与实现,用户根本不知道具体的实现是谁,客户仅仅是面向接口编程,使其从产品实现解耦,抽象工厂模式在切换产品类的时候更加灵活容易。

结束语

1、现在理解文章最开始的那句话是不是很好理解了
普通工厂模式:生产具体的产品,创建的产品是类(Class)
抽象工厂模式:生产抽象的产品,创建的产品是接口(Interface)
2、工厂模式的优点在上述两个例子的小结中已经阐述,工厂模式的缺点也比较明显,就是不太容易扩展新的产品类,需要去改具体的产品类和工厂类。
3、虽然美中不足,但工厂模式是运用非常广泛的一种模式。值得大家学习使用。

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

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

相关文章

【AI面试准备】数据驱动测试思维与实践指南

面试题&#xff1a;数据驱动思维 构建测试数据集&#xff1a;收集代码覆盖率、缺陷历史等数据。 模型训练优化&#xff1a;使用Jupyter Notebook分析特征重要性。 数据驱动思维是一种以数据为核心、基于数据分析结果进行决策的方法论。它强调通过量化分析、模式识别和预测建模…

内存碎片深度剖析

目录 什么是内存碎片 内部碎片的解决 malloc STL二级空间配置器 外部碎片的解决 伙伴系统算法 slab分配器 什么是内存碎片 内存碎片是指在内存中存在的一些不连续的、较小的空闲内存块&#xff0c;这些小块内存由于太小而无法被有效地分配给程序使用&#xff0c;从而导…

flutter 专题 六十一 支持上拉加载更多的自定义横向滑动表格

在股票软件中&#xff0c;经常会看到如下所示的效果&#xff08;ps&#xff1a;由于公司数据敏感&#xff0c;所以使用另一个朋友的一个图&#xff09;。 分析需要后&#xff0c;我先在网上找了下支持横向滑动的组件&#xff0c;最后找到了这个&#xff1a;flutter_horizontal…

0-1背包问题基础概念

一、问题描述 给定一个容量为 W 的背包和 n 个物品。每个物品有一个重量 w[i] 和价值 v[i]。每个物品只能选或不选&#xff08;即“0-1”&#xff09;&#xff0c;求在不超过背包容量的前提下&#xff0c;所能获得的最大总价值。 输入&#xff1a; 背包容量 W&#xff08;in…

使用 Semantic Kernel 快速对接国产大模型实战指南(DeepSeek/Qwen/GLM)

文章目录 使用 Semantic Kernel 快速对接国产大模型实战指南&#xff08;DeepSeek/Qwen/GLM&#xff09;一、引言二、环境准备2.1 开发环境2.2 模型服务配置 三、核心代码实现3.1 会话代码封装3.2 CurModelContext封装3.3 DeepSeek对接示例3.4 Qwen对接示例3.5 GLM对接示例 四、…

Ai时代,运维人如何转型

在AI时代,传统运维向智能运维(AIOps)的转型需要系统性重塑,以下是深度拆解的转型路线图和关键实施要素: 一、认知升级范式转变 1. 演进路线模型(三阶段) 被动响应阶段:人工巡检(→监控覆盖率<30%)主动防御阶段:规则引擎(→告警准确率70%~85%)预测自治阶段:深…

windows鼠标按键自定义任意设置

因为用惯了Linux的鼠标中键的复制黏贴&#xff0c;发现windows下有完全可以实现类似自定义功能的软件&#xff0c;推荐一下&#xff1a; X Mouse Button Control。 免费版足够好用。 软件简介&#xff1a; X Mouse Button Control是一款专业的重新映射鼠标按钮的软件工具&…

怎么看户型好不好?

看房型好不好可从以下方面判断&#xff1a; 空间布局 方正性&#xff1a;户型方正为佳 &#xff0c;此时进深与开间比例在1:1.5左右。方正户型空间利用率高&#xff0c;无采光死角。如手枪型、锯齿型等异形户型&#xff0c;易有拐角、长过道&#xff0c;空间浪费大。动静分区…

基于WOA鲸鱼优化TCN-BiGRU注意力机制网络模型的时间序列预测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a/matlab2024b 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频…

JAVA简单走进AI世界~Spring AI

1、背景 现代 AI 正以前所未有的速度改变着世界。它是基于复杂算法和强大计算能力的技术体系,涵盖了机器学习、深度学习、自然语言处理等多个领域。 在日常生活中,AI 广泛应用于智能语音助手、图像识别、推荐系统等。比如,智能音箱能理解并回应语音指令,为人们提供信息查…

stm32wb55rg (4) 启用usart串口

code repo: 访问gitee 上节课成功点亮了LED&#xff0c;这次来把usart 用起来&#xff0c;毕竟有交互才是系统。 技术准备 首先查看手册&#xff0c;发现mcu有1个usart和1个 lpuart。 usart 的使用需要两个pin&#xff0c;一个接收一个发送。继续查看pin and ball definition…

Python生活手册-NumPy数组创建:从快递分拣到智能家居的数据容器

一、快递分拣系统&#xff08;列表/元组转换&#xff09; 1. 快递单号录入&#xff08;np.array()&#xff09; import numpy as np快递单号入库系统 快递单列表 ["SF123", "JD456", "EMS789"] 快递数组 np.array(快递单列表) print(f"…

数据库-数据类型,表的约束和基本查询操作

一、数值类型 1. 整数类型 类型字节有符号范围无符号范围操作注意事项TINYINT1-128 ~ 1270 ~ 255默认有符号&#xff0c;UNSIGNED定义无符号SMALLINT2-32768 ~ 327670 ~ 65535无符号需显式声明INT4-2^31 ~ 2^31-10 ~ 2^32-1推荐优先使用INTBIGINT8-2^63 ~ 2^63-10 ~ 2^64-1存…

【C语言编译】编译原理和详细过程

文章目录 1. C 语言编译原理和详细过程1.1 预处理阶段1.2 编译阶段1.3 汇编阶段1.4 链接阶段 2. 疑问点解析2.1 三地址码是什么&#xff1f;有什么作用2.2 符号表是什么&#xff1f;有何作用2.3 重定位的含义与作用2.3 符号表和重定位在整个编译过程中的作用2.4 动态链接库.so和…

游戏引擎学习第251天:完成调试层级结构

运行游戏&#xff0c;查看当前调试层级的状态。 我们正在直播中开发一个完整的游戏&#xff0c;目前正进行调试代码的整理和清理工作。现在我们直接进入正题&#xff0c;虽然还不完全确定今天要完成哪些具体内容&#xff0c;但有几个明确的目标&#xff1a; 首先&#xff0c;…

关于Python:9. 深入理解Python运行机制

一、Python内存管理&#xff08;引用计数、垃圾回收&#xff09; Python&#xff08;CPython&#xff09;采用的是&#xff1a; “引用计数为主&#xff0c;垃圾回收为辅” 的内存管理机制。 也就是说&#xff1a; 引用计数机制&#xff1a;负责大部分内存释放&#xff0c;简…

【STM32单片机】#13 RTC实时时钟

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 目录 Uni…

SecureCRT 使用指南:安装、设置与高效操作

目录 一、SecureCRT 简介 1.1 什么是 SecureCRT&#xff1f; 1.2 核心功能亮点 1.3 软件特点 二、SecureCRT 安装与激活 2.1 安装步骤&#xff08;Windows 系统&#xff09; 2.2 激活与破解&#xff08;仅供学习参考&#xff09; 三、基础配置与优化 3.1 界面与编码设…

3.5/Q1,GBD数据库最新一区文章解读

文章题目&#xff1a;Global burden of low vision and blindness due to age-related macular degeneration from 1990 to 2021 and projections for 2050 DOI&#xff1a;10.1186/s12889-024-21047-x 中文标题&#xff1a;1990年至2021年因年龄相关性黄斑变性导致的低视力和失…

【Hive入门】Hive安全管理与权限控制:基于SQL标准的授权GRANT REVOKE深度解析

目录 引言 1 Hive权限模型概述 2 SQL标准授权基础 2.1 核心概念解析 2.2 授权模型工作流程 3 GRANT/REVOKE语法详解 3.1 基础授权语法 3.2 权限回收语法 3.3 参数说明 4 授权场景 4.1 基础授权示例 4.2 列级权限控制 4.3 视图权限管理 5 权限查询与验证 5.1 查看…