范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

老板问我怎么用面向对象的思维编程?

  面向过程OR面向对象面向过程的代码
  在说面向对象前我们来说说什么是面向过程。什么是面向过程呢?
  面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
  举个栗子,比如之前项目组做的付款计划,这里面包含了 A付款,B付款,C付款,D付款 等模块。
  拿 A付款 模块来说,我们在提交付款时,要求: 1.提交前的业务校验(如判断付款金额,预留额度) 2.单据信息填充(金额信息,银行信息,用户信息) 3.付款信息推送第三方系统(如结算系统) 4.信息推送后更新单据信息(单据状态,更新占用额度) 5.消息通知责任人处理付款信息(邮件通知,OA通知,短信通知,微信通知)
  看到这个需求我们会觉得很简单嘛,功能已经很明确,按着这个说明一行一行写代码就行了,于是我们开写: public void submitPayInfo(PayInfoyCmd createParam) {      validateBeforeSubmit(createParam);     updatePayInfo(createParam);     push2PaySettle(createParam);     updateStatusAndPayApply(createParam);     notifyExecutor(createParam); }
  我们将每个功能抽象成一个方法,相应功能写在相应的方法中。这样看上没问题,我们满足了设计原则中的单一职责原则,方法尽可能地做到了短小精悍。但我们仔细读面向过程的解释:
  面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
  发现这不就是我们平时代码写的么,按照常规思路,我们写成了面向过程的代码。
  在我们在刚接触面向对象时就听说过面向对象了。那时书本或者网上是这么解释的
  "面向对象"是专指在程序设计中采用封装、继承、多态和抽象等设计方法。
  那么上面的案例代码也有抽象,也有封装,为什么还是算面向过程思维呢。
  那么什么是面向对象呢?
  我们从哲学上来说: 面向对象 的基本哲学是认为世界是由各种各样具有自己的运动规律和内部状态的对象所组成的;不同对象之间的相互作用和通讯构成了完整的现实世界。因此,人们应当按照现实世界这个本来面貌来理解世界,直接通过对象及其相互关系来反映世界。这样建立起来的系统才能符合现实世界的本来面目。
  这里我理解的是: 万物皆可为对象
  对象包含了自身属性与行为
  功能的交付其实是对象与对象之间的交互
  那么按照这样的想法,上述代码中的校验,三方系统推送,消息通知应该属于各自对象的行为。我们需要创建各自的对象去装载各自的行为。 public void submitPayInfo(PayInfoCmd createParam) {      payInfoSubmitValidator.validateBeforeSubmit(createParam);     updatePayInfo(createParam);     settleApplicationService.push2PaySettle(createParam);     updateStatusAndPayApply(createParam);     notifyHandler.notifyExecutor(createParam); }低耦合,关注功能本身
  要想写出面向对象思维的代码,我们需要遵循面向对象的原则: 高内聚,低耦合 。在面向对象思想中,
  功能交付是对象与对象之间的交付,每个对象承担自己的工作,对象与对象之间应该尽量减少耦合。因此我们需要降低对象之间的耦合,关注对象功能本身。
  我们将上述案例代码继续抽象。发现主要做了几件事情: 前置处理-校验
  本身功能处理
  后置处理
  其实大部分函数方法都可以抽象成三步。
  如果我们不考虑 第3点 的后置处理。 1,2点 就是我们常见的模型。对于一般方法,我们可以抽象为: 1.非业务 2.业务
  我们在复用代码时发现有的情况下是不需要有校验存在的。
  例如在提交时,我们需要业务校验,但是在保存时,又不需要。为此常见做法是在入参添加一个字段: private boolean needSubmit;
  在写代码时,使用if判断,如果needSubmit传true,调用校验方法,传false反之。所以每次写类似代码时,我们都要为是不是一定需要校验操心。
  程序员无法专注与本身业务处理,对于软件质量来说。未必是件好事。
  那么这里我们需要一个低耦合,可插拔的设计。
  这里我决定使用注解。
  tips:善用注解,但别滥用
  注解虽然降低了代码耦合度,简化了开发过程。但内部使用了反射,在一定程度上牺牲了性能。
  注解大家应该不陌生,我们使用Spring系列框架开发,就一定会用到注解,但是我相信大家很少自己开发注解。
  说回正题,我们如何使用注解开发校验功能呢?
  我们来看直接使用示例:
  上述 A付款 提交功能中,提交功能代码里面就是单纯的提交功能,对于校验功能,我们写在了注解中: @ValidatorHandler(validators = PayInfoSubmitValidator.class)
  上面的案例大家可能只会觉得:这个跟代码写在校验类里面直接调用有什么区别呢?
  那我们再来看一个例子,大家都有用过导出功能,比如EasyExcel导出。那么使用这个EasyExcel导出时,我们可以抽象为: 1.查询数据结果集 2.调用EasyExcel方法进行导出
  事实上第2点我们可以交给注解去做,程序员只需要将结果集返回即可。
  那么使用注解后:
  使用注解除了简化业务代码,还有一个重要功能:
  例如在上面的注解校验案列中,我们使用注解校验。后续维护的时候,程序员就不需要进入主体代码,只需要在对应的校验类里面维护即可,保证功能的安全性。 利用面向对象思维简化代码
  我们在编写代码时,需要思考, 这段代码是否可以重复利用
  这段代码是否可以不写
  关于重复利用,我们经常会做,比如抽取成公共的方法。关于代码是否可以不写,我们可能会思考得比较少,一般判断代码是否可以省略,需要看这段代码是不是通用功能。比如我们可以使用拦截器,注解,Spring框架的AOP来减少不必要的代码。
  同样举个例子:
  之前业务开发时,有一个字段接收的数据是Json格式的,并且需要以Json形式入库:
  如上图,数据库有个字段survey_conclusion_options数据是以Json形式储,这里我们要求: 1.create创建时,前端准入Json形式的字符串存储; 2.查询展示时,以List对象形式展示
  那么常规情况下我们会在入库时直接传Json格式的数据,示例如下:
  实体类: public class ConclusionTemplate extends BaseEntity implements Serializable {         ...     @ApiModelProperty(value = "结论选项(json形式存储)")     @Column(name = "conclusion_options")     private String conclusionOptionsJsonArrays;     ... }
  入库: public int createConclusionTemplate(ConclusionTemplate conclusionTemplate) {     BusinessExceptionAssert.checkNotNull(conclusionTemplate, "参数不能为空!!!");     conclusionTemplate.setConclusionOptionsJsonArrays("前端传入")     return this.save(conclusionTemplate); }
  展示: @Data public class ConclusionTemplateVo {     private List conclusionOptions; }public ConclusionTemplateVo getVoById(String id) {     ConclusionTemplateVo vo = new ConclusionTemplateVo();     ConclusionTemplate template = getById(id);    vo.setConclusionOptions(JsonUtils.str2list(template.getConclusionOptionsJsonArrays,ConclusionTemplateOptionVo.class)); }
  这转换我们抽象为: JsonArray ->  JsonUtils转换 -> List实体
  插入的时候我们抽象为: JsonArray -> 数据库 或  List实体  -> JsonUtils转换 -> JsonArray
  那么我们每次存取时都需要在List与Json之间转换。并且程序员需要写这段代码。
  但是在面向对象的思想中,这个Json数组中的每个元素就是一个对象,我们可不可以在代码层中以List的形式存,然后以List的形式取出,中间的Json转换有程序自动去做,不需要开发去手动转。
  我们可以在Entity类中这样写:
  我们在实体类中的这个字段写成List形式的,在上面添加@ColumnType注解。这个注解用来实现List与Json之间的自动互转。然后需要在Mapper.xml文件中配置: 
  我们在这个字段添加typeHandler。
  这样我们下代码存数据的时候就是添加List而不是Json了。
  我们来看ConclusionTemplateTypeHandler中的写法
  通过ConclusionTemplateTypeHandler,我们实现了Json与List的自动互转。 使用设计模式实现面向对象设计
  设计模式相信大家很熟悉,在面试的时候也会被问道:设计模式了解么?
  常见的设计模式如: 单列,工厂,代理,策略 等等。今天我来分享我常用的几种这几模式: 策略模式
  策略模式是一种比较简单的设计模式,生活中做成一件事有几种不同的策略选择供你达成。比如你上班可以选择坐公交上班,可以选择坐地铁上班,也可以选择自驾上班,甚至还可以步行上班。
  如果抽象程代码: if("1".equals(status)) {    return "公交"; } else if("2".equals(status)) {    return "地铁"; } else if("3".equals(status)) {    return "自驾"; } else if("4".equals(status)) {    return "步行"; }
  上面的代码有什么问题呢,就是耦合第很高,如果需要增加、移除、修改算法,需要在这里反复修改,违反了开闭原则。这个问题可以使用策略模式解决。
  如何换成策略模式是什么样的呢?
  上图我们可以知道:策略模式就是将算法调用方与算法实现方分割开来,实现两者之间的解耦。
  我认为策略模式优点是: 算法可自由切换
  避免多重if-else语句
  更好的扩展性
  我们来举个列子:
  文章开头的案列中,在提交付款最后,我们需要发消息通知,例如发OA通知: notifyHandler.notifyExecutor(createParam);
  这里 付款 提交需要发OA通知,同样的 采购付款,预付款,紧急预付款 也需要发OA通知。这里我们不就可以使用策略模式来做么:
  在主体方法我们只需要调用: notifyStrategy.notifyExecutor(createParam);
  各自模块的功能: NotifyStrategy    |__ PayXXANotifyStrategy    |__ PayXXBNotifyStrategy    |__ PayXXCNotifyStrategy    |__ PayXXDNotifyStrategypublic interface NotifyStrategy {    void notifyExecutor(PayInfoCmd createParam); }
  各自策略类实现NotifyStrategy。那么以后我们修改消息通知功能就只需要在策略类中修改,不需要去主体功能方法中。 观察者模式
  什么是观察者模式呢?
  在现实生活中,许多对象都不是独立存在的,其中一个对象的改变往往会导致其它对象的改变。比如:到了下班时间你会下班回家,路上遇到红灯你会停下来,股市行情好了你会追加投资。
  因此我们可以抽象为: 功能A运行,触发了功能B的运行。
  你可能不知道观察者模式这个名词,但你一定用过:例如消息队列的 发布-订阅模型 (生产-消费),我们拿kafka举例:
  kafka发布消息:  ListenableFuture future = kafkaTemplate.send(topic, jsonString);
  消费者订阅消息: @KafkaListener(topics = "${spring.kafka.topic}")  public void listen(ConsumerRecord<?, ?> record) {         log.info("topic={}, offset={}, message={}", record.topic(), record.offset(), record.value());  }
  除了消息中间件的发布-订阅模型属于观察者模式,Zookeeper的watch机制也使用了观察者模式。 public void watcherNode(String path) {     ZkClient connection = zookeeperConfig.getConnection();     connection.subscribeDataChanges(path, new IZkDataListener() {         @Override         public void handleDataChange(String dataPath, Object data) throws Exception {             log.info("路径:{}收到了节点变化:{}", dataPath, data);         }          @Override         public void handleDataDeleted(String s) throws Exception {             log.info("路径:{}收到节点删除");         }     }); }
  利用Zookeeper的watch机制,我们可以设计出很多功能,例如设计可靠性更优良(相对于Redis)的分布式锁,服务发现(注册中心)等。
  我们又回到开头的案列,在提交付款后需要发消息通知: 5.消息通知责任人处理付款信息(邮件通知,OA通知,短信通知,微信通知)
  这里的代码我们可能会这样写: public void notifyExecutor(PayInfoCmd createParam) {     emailNotifyApplicationService.sendEmail(createParam);     oaNotifyApplicationService.sendOaMsg(createParam);     noteNotifyApplicationService.sendNote(createParam);     wechatNotifyApplicationService.pushMsg(createParam); }
  这里我们只是处理消息通知,如果付款之后还有别的操作呢?例如打印付款记录,创建订单,创建物流的等等。如果我们都写在主体代码中,后面万一撤销功能(如撤消邮件通知,微信通知),这样肯定违反了设计原则中的避开原则。
  如果我们的系统是单体系统,我们可以使用Spring的事件机制: public class PayInfoEvent extends ApplicationEvent {     private PayInfo payInfo;      public PayInfoEvent(Object source, PayInfo payInfo) {         super(source);         this.payInfo = payInfo;     }      public PayInfo getpayInfo() {         return payInfo;     }      public void setpayInfo(PayInfo payInfo) {         this.payInfo = payInfo;     } }@Component @Slf4j public class PayInfoEventPublisher {     @Autowired     public ApplicationEventPublisher applicationEventPublisher;      public void publishPayInfoEvent(PayInfo PayInfo) {         log.info("付款提交后消息推送.....");         if (PayInfo == null) {             log.info("无需推送至sap");             return;         }         applicationEventPublisher.publishEvent(new PayInfoEvent(this, PayInfo));     } }
  我们在提交付款后调用消息推送事件: public void submitPayInfo(PayInfoCmd createParam) {      PayInfoSubmitValidator.validateBeforeSubmit(createParam);     updatePayInfo(createParam);     PayInfo PayInfo = BeanUtils.copy(createParam, PayInfo.class);     PayInfoEventPublisher.publishPayInfoEvent(PayInfo); }
  发送之后,需要监听并订阅:
  PayInfoSapEventReceiver @Component @Slf4j public class PayInfoSapEventReceiver {     @Autowired     public PayInfoService PayInfoService;      @EventListener     public void eventHandler(PayInfoEvent PayInfoEvent) {         PayInfo payInfo = PayInfoEvent.getpayInfo();         PayInfoService.putPayInfo2Sap(payInfo);         log.info("付款推送sap事件已处理完毕,单号【{}】", payInfo.getPayCode());     } }
  PayInfoOaEventReceiver @Component @Slf4j public class PayInfoOaEventReceiver {     @Autowired     public PayInfoService PayInfoService;      @EventListener     public void eventHandler(PayInfoEvent PayInfoEvent) {         PayInfo payInfo = PayInfoEvent.getpayInfo();         PayInfoService.putPayInfo2Oa(payInfo);         log.info("付款推送OA事件已处理完毕,单号【{}】", payInfo.getPayCode());     } }
  依此类推,如果我们的系统是分布式的,例如消息推送,订单推送,物流推送都有各自的系统,这里需要远程调用。我们同样使用 发布-订阅机制 ,例如使用kafka等消息队列中间件在业务系统中发布 领域事件 ,在各自业务系统中消费这些领域事件。
  使用观察者模式需要注意: 消息发送成功,接收消息也成功了,但是处理消息时失败了应该怎么办。
  这个问题留给大家思考。
  当我们要取消某个消息推送时,我们只要将对应类中的@EventListener注释掉即可,不需要修改主体代码。
  上面介绍的策略模式和观察者模式都面向对象语言中的设计模式。
  使用策略模式,我们能在面对不同的需求情况更加灵活的做出不同的策略回应,同时策略模式也提升了代码的扩展性。
  使用观察者模式,我们独立了目标与观察者,降低了两者的依赖性,也是面向对象设计中低耦合的体现。 面向对象思维模式代表——基于领域驱动的设计
  文章上面我们谈到 领域事件 。你或许会好奇:什么是领域事件?
  在这之前我们需要弄明白什么是领域驱动设计。
  领域驱动设计(Domain Driven Design)是一种从系统分析到软件建模的一套方法论。以领域为核心驱动力的设计体系。
  领域驱动设计适合产品化,可持续迭代,业务逻辑足够 复杂的业务 系统,对于系统初期业务逻辑相对比较简单的应用,传统MVC架构更具有优势,可以减少一部分认知成本与开发成本。
  这里我们可以简单认为一个领域即为一个服务。
  我认为基于领域驱动的设计更符合面向对象设计的原则,当我们接触到需求的第一步就需要考虑领域模型,而不是将其切割成数据和行为,然后数据用数据库实现,行为使用服务实现,最后造成需求的首肢分离。
  总的来说我们需要先考虑业务语言,而不是数据。
  领域驱动设计将业务语义显性化,更准确的传达业务规则,因此我们可以更清晰的实现代码。
  今天我们简单介绍下在代码中如何运用DDD领域驱动设计模型
  说到DDD,人们首先会讨论充血模型与贫血模型。 贫血模型贫血领域对象
  贫血领域对象(Anemic Domain Object)是指仅用作数据载体,而没有行为和动作的领域对象。
  简单来说,就是只有Getter/Setter方法的实体。既然有贫血领域对象,那也就有充血领域对象。 充血模型充血领域对象
  实体除了Getter/Setter方法,还有描述实体行为和动作的方法
  在充血模型中我们的对象不只有本身的属性,还有相关的行为。来看下面代码:
  上面代码是一个提交进入审批流程的方法,提交后我们需要在后台数据库记录一条提交记录,这个时候需要对数据做一些初始化,例如:初始化审批层级为第一层,初始化节点类型为提交节点,初始化删除标志为未删除。
  如果按照贫血模型来写: public Long submitProcess(ProcessCreateParam createParam) {  ...  process.setDeleted(SystemConstant.ZERO_BYTE);  process.setProcess(SystemConstant.ONE_BYTE);  process.setType(SystemConstant.ONE_BYTE);  ... }
  贫血模型中,我们将对象初始化的具体细节交给了submitProcess()方法来做。然后从面向对象的角度来说,这些是属于对象本身需要做的事情,如果在其他方法中,我们又需要给对象标上非删除标记,初始化层级,设置提交节点。那么在这些方法又要同样的事情。我们为何不将这件事情交给对象本身来做呢?
  在充血模型中我们可以这样写:
  需要时我们直接通过对象调用即可: public Long submitProcess(ProcessCreateParam createParam) {                 ...         Process process = BeanUtils.copy(createParam, Process.class);         process.unDeleted();         //初始化层级:1         process.initLevel();         //初始化节点类型:提交节点         process.submitType();         ...        }
  回到文章开头所说的面向对象设计,充血模型无疑是对面向对象一个很好的诠释。
  关于DDD领域驱动设计,推荐书籍: 《领域驱动设计:软件核心复杂性应对之道》
  《实现领域驱动设计》为什么我们在使用贫血模型
  看了上面的代码,我们可能会疑问: 我使用贫血模型开发挺好的啊?为什么还要使用充血模型?也没看出什么不一样啊?
  传统开发模式的贫血模型,将数据与业务彻底隔离。对象通过Getter/Setter方法修改属性,这样对象属性可能会被随意修改,从而违反了面向对象中的封装特性。
  其实这样的编程方式是传统的面向过程思维编程方式,面向过程的思维方式是符合我们人类的大脑思维逻辑的,不需要太多的设计模式和过多的设计思考。其实我们在开发中存在这样的思维惯性:怎么方便怎么来,代码编写很简单,别人也容易接受。
  因此我总结为什么人们更愿意使用贫血模型呢: 充血模型相对贫血模型存在一定的设计难度,你需要多花时间思考哪些是对象本身的行为
  面向过程的编程思想根深蒂固,很难改变
  对代码没有太大负责态度,认为怎么简单怎么来我们需要使用充血模型么
  DDD领域驱动设计是应对复杂的软件设计而产出的一种思维模式,遵循面向对象的设计思想。在复杂的系统中,我们使用贫血模型(面向过程思维)开发,那最后的结果是 点连成线,线交织成网,密密麻麻不可维护
  然而我们大部分负责的系统并不复杂,我的建议是: 朝充血模型思维方式靠齐我的思考
  如果你还在抱怨自己的工作只是 简单,重复,机械的增删改查 。那么建议你多做一些的思考: 1.我的代码是不是面向对象的代码 2.我的代码设计是否遵循 高内聚,低耦合的设计标准 3.我的代码是否遵循设计原则,如单一职责原则,开闭原则等 4. ...
  从细节处提升自己。

你应该吃10种富含维生素E的水果来保持健康真的不喜欢海鲜坚果和种子,以及其他传统上富含维生素E的来源吗?如果您正在寻找一种快速无忧的替代品,您可能想知道水果是否可以解决问题。水果确实可以与其他维生素E来源一起增加您的维生素西药降血压副作用大?中成药,安宫降压丸牛黄降压丸,如何选择高血压是一种常见的疾病,会引起其他并发症。比如心力衰竭脑梗肾病和高血压性糖尿病。因此必须要积极治疗,不能有一丝松懈的心态。另外饮食方面也要注意,不可过量吃高热量高油脂的食物。药物治颠覆认知权威研究发现高盐饮食可以抑制肿瘤?盐到底要怎么吃?盐是人们日常生活中必不可少的调味品,缺了它就会饮食无味,还觉得软弱无力,但若长期摄入过多,则很容易影响健康,诱发疾病。目前普遍都在倡导一种减盐的健康饮食理念,人们越来越注重高盐饮食有一种很显瘦的穿法,叫短上衣阔腿裤,专治腿粗胯宽,真时髦阔腿裤也算是我们的老朋友了,几乎一年四季都能看到它的身影。可是正因如此,让阔腿裤的穿法越来越大众化,如果你也对阔腿裤的搭配很感兴趣,那可千万不能错过今日的穿搭分享。今天就来为大家安喝茶的错误方式,你有吗喝茶是雅事亦是俗事,更是平常事。日常生活中茶伴随着我们的生活起居交际应酬茶余饭后。喝茶的方式有很多种,有养生的有伤身的,有正确的,也有错误的,可谓一阴一阳知味道,正确的喝茶方式让我春天养背,人活百岁!5个最简单有效的养背方法,跟着做年轻10岁我们常说春天养肝很重要,但补阳气祛湿同样不可忽视。这主要还是因为,经过一个冬天,我们体内脏腑积累的寒湿浊气,在春天是排出的好时机。而要祛除这些,还得需要体内阳气的配合。中医认为让体医生推荐热姜水的17种养生之道,鲜为人知,建议收藏分享姜亦称为生姜,属于姜科,是多年生草本植物,中国各地均有栽培。根茎的形状多分枝或成掌状,青黄色深黄色到浅褐色,味芳香而辛辣。提到生姜,相信大家都非常熟悉,它是一种常见的调味品,几乎在薯类怎样吃更健康?对比新旧版本的膳食宝塔可以发现,新版膳食宝塔的谷薯类总量不变,仍然是250400克。但是把谷类和薯类分开,其中薯类平均每天50100克。这是为了强调薯类在主食中的重要性,以及更好去湿气重的人,夏季饮食有讲究!牢记4点,或有助远离湿气困扰随着物质生活的改善,很多家庭把鸡鸭鱼肉等荤菜当成主食,虽然说荤菜能给我们补充蛋白质和脂肪等人们所需要的物质,但是光吃荤菜是不行的,君不见,现实生活当中的大肥头和小胖墩越来越多了。近可预防痴呆延缓衰老!少吃好处多多,吃多少合适?吃了吗?这是我们见面经常打的招呼,足以说明吃在我们心中的分量。谁都需要吃饭,但是我们早已过了饥不果腹的苦难日子,如今,我们需要抵制各种美吃了吗?这是我们见面经常打的招呼,足以说明吃母其弥雅真是瑜伽女王,斜边吊带裙挺宽松,但看得出身材多妙今天穿什么变美百科全书穿搭红黑榜裙装穿搭在很多人在穿搭领域中占比相对较大的一种搭配方式,裙装种类的丰富也经常会让女性在挑选的时候会有一种十分凌乱无序的感觉,因为选择的增多也意味着自
要弯道超车!俄罗斯决定绕过5G,直接开发6G网络近日,俄罗斯斯科尔科沃科学技术研究院和无线电研究所正在准备开发该国国内第六代(6G)通信设备。这意味着,俄罗斯决定弯道超车,绕过5G直接开发6G网络。俄罗斯数字发展通信和大众传媒部欢太金融靠谱吗?一个正规且专业的综合金融服务平台在互联网时代下,大量线下消费场景都被搬到了线上,金融行业也不例外。随着技术的不断发展,互联网金融已成为大众的一种生活方式,相应的互联网金融平台如雨后春笋般破土而出。在众多互联网金融Nanosatellite物联网运营商Astrocast与Soracom合作开发SatIoT解决方案据telecompaper网7月29日报道,全球领先的纳米卫星物联网网络运营商Astrocast和高级物联网连接的全球提供商Soracom宣布建立合作伙伴关系,将AstrocastiPhone抢下华为市场份额,但苹果大中华区收入下滑1,库克大促不是清库存本文来源时代财经作者王婷图源pixabay美东时间7月28日盘后,苹果公司发布截至6月25日的2022财年第三财季业绩。此前市场预期,苹果期内营收同比增速将下滑至2,创下2020年嫌中国空间站里用中文?狭隘与傲慢有多可笑随着中国空间站问天实验舱发射成功,美版知乎Quora上一个关于中国航天的问题也跟着翻红。这位博主在帖子里质疑在新发射的太空船上只使用中文,是否说明这个国家超级自我封闭?不出意外,评荣耀千元机开始真香,超窄边框256GB4800mAh,从1999降至1599元众所周知,从华为脱离出来的荣耀,变化还是相当大,在华为的时候,荣耀手机性价比相当高,甚至和小米或者红米手机有得一拼,前几年的618或者双11活动,荣耀还反超小米,拿到过手机销量冠军摩托罗拉motoX30Pro真机曝光,后摄2亿像素主摄镜头摩托罗拉将会在8月2日召开新品发布会,一次性发布两款旗舰手机,分别是首款2亿像素的motoX30Pro以及折叠屏手机motorazr2022。近日,motoX30Pro的真机渲染图林志颖驾驶特斯拉遭遇车祸起火,新能源汽车着火保险怎么赔?7月22日,台湾男星林志颖与其儿子遭遇车祸,因不明原因自撞电线杆,整台车起火燃烧,不过好在并未受困,两人被及时送往医院救治。据台媒报道称,医师透露林志颖目前人清醒,但颜面骨折肩膀的2021年麻省理工科技评论50家聪明公司榜单出炉,OPPO上榜7月29日,EmTechChina全球新兴科技峰会暨50家聪明公司发布仪式举行。OPPO凭借首个自主研发的影像专用NPU芯片马里亚纳MariSiliconX,入选2021年麻省理工烧光400亿造了个寂寞!贾跃亭FF量产车再度延期公司没钱了近期,法拉第未来(简称FF公司)已经明确表示将会继续推迟FF91的交付时间,预计会推迟至2022年第三季度或第四季度。这也是该公司第N次宣布首款量产车的延迟交付。显然,大多数网友对百度25万元8颗激光雷达,再送辆车,能自动驾驶!7月21日的百度世界大会上,百度发布了第六代无人车ApolloRT6,这台车搭载了8颗激光雷达,成本价25万元,2023年就会正式上市。可能大家都没听说过百度的无人车,那为大家简单