java抽象工厂实战与总结
文章目录
- 一、工厂模式(三种)
- 1.简单工厂模式
- 1.1 概念:
- 1.2 `使用场景`:
- 1.3 模型图解:
- 1.4 伪代码:
- 2.工厂方法模式
- 2.1 概念:
- 2.2 `使用场景`:
- 2.3 模型图解:
- 2.4 伪代码
- 3.抽象工厂模式
- 3.1 概念
- 3.2 `使用场景`
- 3.3 模型图解:以两层模型做例子
- 3.4 伪代码
- 3.4.1 以品牌角度设计工厂
- 3.4.2 以手机角度设计工厂
- 3.5 实战:抽象工厂 + 简单工厂模式 +策略模式
- 3.5.1 业务方法调用
- 3.5.2 抽象工厂创建二级工厂,定义获取业务对象接口(二级工厂去创建具体的业务对象)
- 3.5.3 二级工厂 获得对象
- 3.5.3 二级工厂 具体的业务对象
- 3.5.3 处理的业务
- 补充:6大设计原则
- 3.6 总结:
一、工厂模式(三种)
1.简单工厂模式
1.1 概念:
通过一个工厂类来创建对象,根据不同的参数或条件返回相应的对象实例。
隐藏了对象的创建细节,客户端只需通过工厂类获取对象而不需要直接实例化对象。
1.2 使用场景
:
使用者:根据不同的参数或条件返回相应的对象实例
1.3 模型图解:
角色:手机总工厂、参数、手机、小米手机、华为手机
后续补充:
1.4 伪代码:
public class SimpleFactoryTest {static class SimpleFactory {static SimpleFactoryTest.Mobile createMobile(int mobileType) throws Exception {if (mobileType == 1) {return new SimpleFactoryTest.HuaWei();} else if (mobileType == 2) {return new SimpleFactoryTest.XiaoMi();} else {throw new Exception("手机类型不存在!!!");}}}public static class Mobile {protected void call() {System.out.println("mobile...");}}public static class HuaWei extends Mobile {public void call() {System.out.println("huaWei...");}}public static class XiaoMi extends Mobile {public void call() {System.out.println("xiaomi...");}}public static void main(String[] args) throws Exception {SimpleFactoryTest.Mobile mobile = SimpleFactory.createMobile(1);mobile.call();}
}
2.工厂方法模式
2.1 概念:
定义了一个创建对象的接口,具体对象的创建由对象工厂决定。
使得对象的创建延迟到子类工厂,从而实现了对扩展开放、对修改关闭的原则。
2.2 使用场景
:
使用者:根据不同的子工厂创建相应的对象实例
2.3 模型图解:
角色:手机总工厂、小米手机工厂、华为手机工厂、手机、小米手机、华为手机
后续补充
2.4 伪代码
public class FactoryMethodTest {interface FactoryMethod {Mobile createMobile();}static class HuaweiFactory implements FactoryMethod {@Overridepublic Mobile createMobile() {return new Huawei();}}static class XiaomiFactory implements FactoryMethod {@Overridepublic Mobile createMobile() {return new Xiaomi();}}static class Mobile {protected void call() {System.out.println("mobile...");}}static class Huawei extends Mobile {@Overridepublic void call() {System.out.println("huawei...");}}static class Xiaomi extends Mobile {@Overridepublic void call() {System.out.println("xiaomi...");}}public static void main(String[] args) {final HuaweiFactory huaweiFactory = new HuaweiFactory();final Mobile mobile = huaweiFactory.createMobile();mobile.call();}
}
3.抽象工厂模式
3.1 概念
抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象。
通过使用抽象工厂及其产品接口来创建对象,从而将客户端与具体的产品实现解耦。
3.2 使用场景
适用:三层关系
产品 | 品牌 | 子品牌 |
---|---|---|
手机 | 华为手机 | Mate60 / P60手机 …等 |
手机 | 小米手机 | 红米 / Note2 手机 … 等 |
适用:两层关系
产品 | 品牌 |
---|---|
手机 | 华为 |
电脑 | 小米 |
3.3 模型图解:以两层模型做例子
角色::总工厂、小米工厂、华为工厂、小米手机、华为手机、小米路由器、华为路由器
3.4 伪代码
3.4.1 以品牌角度设计工厂
/*** descr: 以品牌角度设计工厂** @date: 2024/1/24**/
public interface AbstractFactory {Phone createPhone();Computer createComputer();class HuaweiFactory implements AbstractFactory {@Overridepublic Phone createPhone() {return new HuaweiPhone();}@Overridepublic Computer createComputer() {return new HuaweiComputer();}}class XiaomiFactory implements AbstractFactory {@Overridepublic Phone createPhone() {return new XiaomiPhone();}@Overridepublic Computer createComputer() {return new XiaomiComputer();}}class HuaweiPhone implements Phone {@Overridepublic void call() {System.out.println("huawei call...");}}class HuaweiComputer implements Computer {@Overridepublic void play() {System.out.println("huawei play...");}}class XiaomiPhone implements Phone {@Overridepublic void call() {System.out.println("xiaomi play...");}}class XiaomiComputer implements Computer {@Overridepublic void play() {System.out.println("xiaomi play...");}}interface Phone {void call();}interface Computer {void play();}
}
3.4.2 以手机角度设计工厂
代码目录结构:
1.测试类 及常量类
1.1 测试类
/*** descr** @author: bjh* @date: 2024/1/27**/
public class AbstractFactoryTest {public static void main(String[] args) {doBiz(Constant.BRAND_HUAWEI, Constant.MODEL_HUAWEI_MATE60);doBiz(Constant.BRAND_XIAOMI, Constant.MODEL_XIAOMI_K20);}/*** 业务方法:** @param brand 品牌* @param modelName 机型*/public static void doBiz(String brand, String modelName) {final AbstractFactory factory = AbstractFactory.getFactory(brand);final Phone phone = factory.createPhone(modelName);phone.call();}}
1.2 常量类
/*** descr:便于管理和维护魔法值** @author: bjh* @date: 2024/1/27**/
public interface Constant {String BRAND_HUAWEI = "huawei";String BRAND_XIAOMI = "xiaomi";String MODEL_HUAWEI_MATE60 = "mate60";String MODEL_HUAWEI_P20 = "p20";String MODEL_XIAOMI_K20 = "k20";
}
2.抽象工厂
/*** descr: 抽象总工厂;* 1.采用简单工厂方法模式获得二级工厂* 2.定义创建手机的接口方法** @author: bjh* @date: 2024/1/26**/
public abstract class AbstractFactory {public abstract Phone createPhone(String modalName);public static AbstractFactory getFactory(String brand) {// 此处三木运算符使用不严谨,实际编码不建议这样写return Constant.BRAND_HUAWEI.equals(brand) ? new HuaweiPhoneFactory() : new XiaomiPhoneFactory();}
}
3.二级工厂(实际工厂)
3.1 华为手机工厂
/*** descr: 华为手机工厂,生成华为手机** @author: bjh* @date: 2024/1/27**/
public class HuaweiPhoneFactory extends AbstractFactory {@Overridepublic Phone createPhone(String modalName) {// 此处三木运算符使用不严谨,实际编码不建议这样写return Constant.MODEL_HUAWEI_MATE60.equals(modalName) ? new Mate60Phone() : new P20Phone();}
}
3.2 小米手机工厂
/*** descr** @author: bjh* @date: 2024/1/27**/
public class XiaomiPhoneFactory extends AbstractFactory {@Overridepublic Phone createPhone(String modalName) {// 此处写法不严谨,实际编码不建议这样写return new K20Phone();}
}
4.抽象手机
/*** descr:手机产品** @author: bjh* @date: 2024/1/26**/
public abstract class Phone {// 机型名称protected String modelName;// 是否支持卫星通话:小米不支持,华为支持protected Boolean satellitePhone;// 公有业务方法:策略模式abstract public void call();
}
5.华为抽象手机与小米抽象手机
5.1 华为抽象手机
/*** descr:抽象的华为手机,定义华为手机特有的业务** @author: bjh* @date: 2024/1/26**/
public abstract class HuaweiPhone extends Phone {// 定义华为手机相关业务: 拨打卫星电话protected abstract void callSatellite();// 支持卫星电话private Boolean satellitePhone = true;
}
5.2 小米抽象手机
/*** descr:抽象的小米手机,定义小米手机特有的业务** @author: bjh* @date: 2024/1/26**/
public abstract class XiaomiPhone extends Phone {//小米手机便宜protected String cheap = "有点便宜!";//不支持卫星电话private Boolean satellitePhone = false;
}
- 实际手机产品:mate60、p20、k20
6.1 mate60
/*** descr 实际华为产品:mate60** @author: bjh* @date: 2024/1/27**/
public class Mate60Phone extends HuaweiPhone {private String modelName = "华为mate60";@Overridepublic void call() {System.out.println(this.modelName + "拨打电话...");}@Overrideprotected void callSatellite() {System.out.println(this.modelName + " >> 拨打卫星电话");}
}
6.2 p20
/*** descr 实际华为产品:P20** @author: bjh* @date: 2024/1/27**/
public class P20Phone extends HuaweiPhone {private String modelName = "华为P20";@Overridepublic void call() {System.out.println(this.modelName + "拨打电话...");}@Overrideprotected void callSatellite() {System.out.println(this.modelName + ">> 拨打卫星电话");}
}
6.3 k20
/*** descr 实际小米产品:K20** @author: bjh* @date: 2024/1/27**/
public class K20Phone extends XiaomiPhone {private String modelName = "小米K20";@Overridepublic void call() {// 抽取变量提高代码可维护性,HashMap源码中有类似这样写法String modalName = this.modelName;System.out.println(modalName + super.cheap);System.out.println(modalName + "拨打电话...");}
}
3.5 实战:抽象工厂 + 简单工厂模式 +策略模式
代码目录结构:
3.5.1 业务方法调用
/*** 根据业务类型计算真正需要动账的存欠类型** @param materialInboundDO* @param walletTypeAndWeight* @return*/private Map<String, BigDecimal> doBizType(MaterialInboundDO materialInboundDO, Map<String, BigDecimal> walletTypeAndWeight) {final AbstractFactory factory = AbstractFactory.getFactory(materialInboundDO.getBillType());final MaterialWalletHandler materialInboundBean = factory.getMaterialInboundOutboundBean(materialInboundDO.getBizType());return materialInboundBean.doBizType(walletTypeAndWeight);}
3.5.2 抽象工厂创建二级工厂,定义获取业务对象接口(二级工厂去创建具体的业务对象)
/*** 抽象工厂解决供应商/客户来料不同的业务类型对客户钱包的动账变化** @date: 2023/7/18**/
public abstract class AbstractFactory {/*** 获得单据类型工厂** @param billType 单据类型* @return*/public static AbstractFactory getFactory(String billType) {if (BillTypeEnum.MATERIAL_CUSTOMER_IN.getKey().equals(billType)) {return new InboundCustomerFactory();} else if ( BillTypeEnum.MATERIAL_SUPPLIER_IN.getKey().equals(billType)) {return new InboundSupplierFactory();} else if (BillTypeEnum.MATERIAL_CUSTOMER_OUT.getKey().equals(billType)) {return new OutboundCustomerFactory();} else if (BillTypeEnum.MATERIAL_SUPPLIER_OUT.getKey().equals(billType)) {return new OutboundSupplierFactory();}throw new ServiceException("原料业务工厂不存在");}/*** 获得业务对象** @param bizType 业务类型* @return*/public abstract MaterialWalletHandler getMaterialInboundOutboundBean(String bizType);
}
3.5.3 二级工厂 获得对象
/*** descr 客户来料工厂** @date: 2023/7/18**/
public class InboundCustomerFactory extends AbstractFactory {@Overridepublic InboundCustomerHandler getMaterialInboundOutboundBean(String bizType) {if (BizTypeEnum.M_CUSTOMER_IN.getKey().equals(bizType)) {return new InboundCustomerIn();}throw new ServiceException("客户来料业务类型不存在");}
}
3.5.3 二级工厂 具体的业务对象
/*** descr 客户:客户来料** @date: 2023/7/18**/
public class InboundCustomerIn implements InboundCustomerHandler {@Overridepublic Map<String, BigDecimal> doBizType(Map<String, BigDecimal> walletTypeAndWeight) {return walletTypeAndWeight;}
}
3.5.3 处理的业务
顶层接口,如下子业务处理方式
/*** descr 来料/出料业务定义接口** @date: 2023/7/18**/
public interface MaterialWalletHandler {Map<String, BigDecimal> doBizType(Map<String, BigDecimal> walletTypeAndWeight);}
中间层子接口之一:用于规范业务
/*** descr 客户来料接口** @date: 2023/7/18**/
public interface InboundCustomerHandler extends MaterialWalletHandler {}
中间层接口实现1:用于处理业务
/*** descr 客户:客户来料** @date: 2023/7/18**/
public class InboundCustomerIn implements InboundCustomerHandler {@Overridepublic Map<String, BigDecimal> doBizType(Map<String, BigDecimal> walletTypeAndWeight) {return walletTypeAndWeight;}
}
中间层接口实现2:用于处理业务
/*** descr 供应商:发料兑料** @date: 2023/7/18**/
public class OutboundSupplierMix implements OutboundSupplierHandler {@Overridepublic Map<String, BigDecimal> doBizType(Map<String, BigDecimal> walletTypeAndWeight) {final HashMap<String, BigDecimal> walletTypeAndWeightMap = new HashMap<>(walletTypeAndWeight);walletTypeAndWeightMap.remove(WalletTypeEnum.CASH.getKey());return walletTypeAndWeightMap;}
}
补充:6大设计原则
1.单一职责
2.开放封闭
3.接口隔离
4.里氏替换
5.依赖倒置
6.迪米特法则
转送:
java常用设计模式
3.6 总结:
- 以上实战中,代码没有写的很完美,还有许多改善的地方
- 抽象工厂在实际运用中比一般都例子都相对复杂;或可能写的理解的有所欠缺
- 抽象工厂定义了对象怎么创建;策略模式定义了业务怎么实现
- 一般抽象工厂模式都想要依托简单工厂或工厂方法模式创建二级工厂;在实践中一般会搭配策略模式或模板方法模式去处理相关业务
- 设计模式的使用主要是对业务代码进行简化或抽象,尽量符合6大设计原则;在技术人员沟通中,只要说出某种设计模式,就能知道业务大概是怎么处理的,极大的减少了沟通成本
相关文章:

java抽象工厂实战与总结
文章目录 一、工厂模式(三种)1.简单工厂模式1.1 概念:1.2 使用场景:1.3 模型图解:1.4 伪代码: 2.工厂方法模式2.1 概念:2.2 使用场景:2.3 模型图解:2.4 伪代码 3.抽象工厂…...

Compose | UI组件(六) | 选择框
文章目录 前言Checkbox 复选框的含义Checkbox 复选框的使用Switch 单选框的含义Switch 单选框的使用Slider 滑竿组件的含义Slider 滑竿组件的使用 总结 前言 随着移动端的技术不断更新迭代,Compose也运用的越来越广泛,很多人都开始学习Compose 本文主要…...

C++拷贝构造函数、赋值学习整理:
拷贝构造函数: 概念: 构造函数的第一个参数,是类本身的const引用(一般情况下没有其他参数,少数情况:其他参数必须有默认值!)称此类构造函数为拷贝构造函数 特征: 1&am…...

[亲测源码]ps软件网页版在线使用 PS网站程序源码 photoshop网页版源码 网页版的ps软件源码
在线PS作图修图网页版PHP网站源码,PHP在线照片图片处理PS网站程序源码photoshop网页版。 有很多朋友们都是在用PS作图的,众所周知在使用和学习PS时是需要下载软件的,Photoshop软件对电脑配置也是有一定要求的,今天就为大家带来一…...

前端大厂面试题探索编辑部——第二期
目录 题目 单选题1 题解 关于TCP 关于UDP 单选题2 题解 A选项的HTTP是否是无状态协议 B选项的HTTP支持的方法 C选项的关于HTTP的状态码 D选项HTTP协议的传输格式 题目 单选题1 1.以下哪个描述是关于 TCP 和 UDP 的区别() A. TCP 是无连接的…...

yaml学习笔记
文章目录 yaml语言学习yaml 简介yaml 和json 区别基本语法数据类型YAML 对象YAML 数组锚点和引用纯量 参考文档 yaml语言学习 最近发现在学习k8s中各种配置文件 都是使用的yaml 这种格式, 包括 docker-compose.yaml 也都是用这个格式配置部署项目信息,我就了解了一下这个语法就…...

深度强化学习(王树森)笔记04
深度强化学习(DRL) 本文是学习笔记,如有侵权,请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接:https://github.com/wangshusen/DRL 源代码链接:https://github.c…...

openssl3.2/test/certs - 074 - CT entry
文章目录 openssl3.2/test/certs - 074 - CT entry概述笔记setup074.shsetup074_sc1.shsetup074_sc2.shsetup074_sc3.shEND openssl3.2/test/certs - 074 - CT entry 概述 openssl3.2 - 官方demo学习 - test - certs 笔记 setup074.sh #! /bin/bash# \file setup074.sh# o…...

Angular组件(一) 分割面板ShrinkSplitter
Angular组件(一) 分割面板ShrinkSplitter 前言 分割面板在日常开发中经常使用,可将一片区域,分割为可以拖拽整宽度或高度的两部分区域。模仿iview的分割面板组件,用angular实现该功能,支持拖拽和[(ngModel)]双向绑定的方式控制区…...

抖音详情API:视频内容获取与解析技巧
一、引言 抖音是一款广受欢迎的短视频分享平台,每天都有大量的用户在抖音上分享自己的生活点滴和创意作品。对于开发者而言,如何获取并解析抖音上的视频内容,是一项极具挑战性的任务。本文将详细介绍抖音详情API,以及如何使用它来…...

SpringBoot中实现阿里云OSS对象存储
背景 在业务中我们往往需要上传文件如图片,文件上传,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发抖音、发朋友圈都用到了文件上传功能。 实现文件…...

大型语言模型 (LLM)全解读
一、大型语言模型(Large Language Model)定义 大型语言模型 是一种深度学习算法,可以执行各种自然语言处理 (NLP) 任务。 大型语言模型底层使用多个转换器模型, 底层转换器是一组神经网络。 大型语言模型是使用海量数据集进行训练…...

Unity - gamma space下还原linear space效果
文章目录 环境目的环境问题实践结果处理要点处理细节【OnPostProcessTexture 实现 sRGB 2 Linear 编码】 - 预处理【封装个简单的 *.cginc】 - shader runtime【shader需要gamma space下还原记得 #define _RECOVERY_LINEAR_IN_GAMMA】【颜色参数应用前 和 颜色贴图采样后】【灯…...

Rabbitmq调用FeignClient接口失败
文章目录 一、框架及逻辑介绍1.背景服务介绍2.问题逻辑介绍 二、代码1.A服务2.B服务3.C服务 三、解决思路1.确认B调用C服务接口是否能正常调通2.确认B服务是否能正常调用A服务3.确认消息能否正常消费4.总结 四、修改代码验证1.B服务异步调用C服务接口——失败2.将消费消息放到C…...

专业120+总分400+海南大学838信号与系统考研高分经验海大电子信息与通信
今年专业838信号与系统120,总分400,顺利上岸海南大学,这一年的复习起起伏伏,但是最后还是坚持下来的,吃过的苦都是值得,总结一下自己的复习经历,希望对大家复习有帮助。首先我想先强调一下专业课…...

如何区分 html 和 html5?
HTML(超文本标记语言)和HTML5在很多方面都存在显著的区别。HTML5是HTML的最新版本,引入了许多新的特性和元素,以支持更丰富的网页内容和更复杂的交互。以下是一些区分HTML和HTML5的关键点: 新特性与元素:H…...

Ps:将文件载入堆栈
Ps菜单:文件/脚本/将文件载入堆栈 Scripts/Load Files into Stack 将文件载入堆栈 Load Files into Stack脚本命令可用于将两个及以上的文件载入到同一个 Photoshop 新文档中。 载入的每个文件都将成为独立的图层,并使用其原始文件名作为图层名。 Photos…...

【格密码基础】:补充LWE问题
目录 一. LWE问题的鲁棒性 二. LWE其他分布选择 三. 推荐文献 四. 附密码学人心中的顶会 一. LWE问题的鲁棒性 robustness,翻译为鲁棒性 已有的论文表明,及时敌手获取到部分关于秘密和error的信息,LWE问题依旧是困难的,这能…...

【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
阅读导航 引言一、特殊类 --- 不能被拷贝的类1. C98方式:2. C11方式: 二、特殊类 --- 只能在堆上创建对象的类三、特殊类 --- 只能在栈上创建对象的类四、特殊类 --- 不能被继承的类1. C98方式2. C11方法 总结温馨提示 引言 在面向对象编程中࿰…...

VMware虚拟机部署Linux Ubuntu系统
本文介绍基于VMware Workstation Pro虚拟机软件,配置Linux Ubuntu操作系统环境的方法。 首先,我们需要进行VMware Workstation Pro虚拟机软件的下载与安装。需要注意的是,VMware Workstation Pro软件是一个收费软件,而互联网中有很…...

RFID标签:数字时代的智能身份
在数字时代,RFID标签(Radio-Frequency Identification)成为物联网(IoT)中不可或缺的一环。作为一种小巧却功能强大的设备,RFID标签在各个领域的应用不断扩展,为我们的生活和工作带来了新的可能性…...

《动手学深度学习(PyTorch版)》笔记3.2
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过。…...

elasticsearch8.x版本docker部署说明
前提,当前部署没有涉及证书和https访问 1、环境说明,我采用三个节点,每个节点启动两个es,用端口区分 主机角色ip和端口服务器Amaster192.168.2.223:9200服务器Adata192.168.2.223:9201服务器Bdata,master192.168.2.224:9200服务器Bdata192.1…...

使用scyllaDb 或者cassandra存储聊天记录
一、使用scyllaDb的原因 目前开源的聊天软件主要还是使用mysql存储数据,数据量大的时候比较麻烦; 我打算使用scyllaDB存储用户的聊天记录,主要考虑的优点是: 1)方便后期线性扩展服务器; 2)p…...

Visual Studio如何修改成英文版
1、打开 Visual Studio Installer 2、点击修改 3、找到语言包,选择需要的语言包,而后点击修改 4、等待下载 5、 安装完成后启动Visual Studio 6、在工具-->选项-->环境-->区域设置-->English并确定 7、重启 Visual Studio,配置…...

gin中使用swagger生成接口文档
想要使用gin-swagger为你的代码自动生成接口文档,一般需要下面三个步骤: 按照swagger要求给接口代码添加声明式注释,具体参照声明式注释格式。使用swag工具扫描代码自动生成API接口文档数据使用gin-swagger渲染在线接口文档页面 第一步&…...

最新AI创作系统ChatGPT网站系统源码,Midjourney绘画V6 ALPHA绘画模型,ChatFile文档对话总结+DALL-E3文生图
一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧。已支持GPT…...

解析dapp:从底层区块链看DApp的脆弱性和挑战
每天五分钟讲解一个互联网只是,大家好我是啊浩说模式Zeropan_HH 在Web3时代,去中心化应用程序(DApps)已成为数字经济的重要组成部分。它们的同生性,即与底层区块链网络紧密相连、共存亡的特性,为DApps带来…...

机器学习整理
绪论 什么是机器学习? 机器学习研究能够从经验中自动提升自身性能的计算机算法。 机器学习经历了哪几个阶段? 推理期:赋予机器逻辑推理能力 知识期:使机器拥有知识 学习期:让机器自己学习 什么是有监督学习和无监…...

RISC-V常用汇编指令
RISC-V寄存器表: RISC-V和常用的x86汇编语言存在许多的不同之处,下面将列出其中部分指令作用: 指令语法描述addiaddi rd,rs1,imm将寄存器rs1的值与立即数imm相加并存入寄存器rdldld t0, 0(t1)将t1的值加上0,将这个值作为地址,取…...