ARTS 打卡第三周(2023.8.28~2023.9.1)

164 阅读6分钟

1. Algorithm 一道算法题

本周算法题为多数元素,我写的题解为:投票算法计算众数

本题比较有趣的一点是使用摩尔投票法解决问题,核心为数两两抵消,剩下的一定为众数,并且只有该算法满足时间复杂度和空间复杂度,我自己想的map、排序等都不能同时满足时间和空间复杂度

2. Review 读一篇英文文章

本周阅读的英文文章为 Inversion of Control Containers and the Dependency Injection pattern

该文章篇幅过长,分为多次进行阅读

Inversion of Control Containers and the Dependency Injection pattern

控制反转容器和依赖注入模式

In the Java community there's been a rush of lightweight containers that help to assemble components from different projects into a cohesive application. Underlying these containers is a common pattern to how they perform the wiring, a concept they refer under the very generic name of "Inversion of Control". In this article I dig into how this pattern works, under the more specific name of "Dependency Injection", and contrast it with the Service Locator alternative. The choice between them is less important than the principle of separating configuration from use.

在Java社区中,出现了一系列轻量级容器,它们帮助将来自不同项目的组件组装成一个有机的应用程序。在这些容器的内部,它们执行连接的方式遵循一个通用的模式,这个概念被称为“控制反转”。在本文中,我将深入探讨这个模式的工作原理,更具体地称为“依赖注入”,并将其与服务定位器的替代方案进行对比。选择它们之间的差异远不如将配置与使用的原则分离重要。

One of the entertaining things about the enterprise Java world is the huge amount of activity in building alternatives to the mainstream J2EE technologies, much of it happening in open source. A lot of this is a reaction to the heavyweight complexity in the mainstream J2EE world, but much of it is also exploring alternatives and coming up with creative ideas. A common issue to deal with is how to wire together different elements: how do you fit together this web controller architecture with that database interface backing when they were built by different teams with little knowledge of each other. A number of frameworks have taken a stab at this problem, and several are branching out to provide a general capability to assemble components from different layers. These are often referred to as lightweight containers, examples include PicoContainer, and Spring.

企业Java世界中令人愉悦的事情之一是在构建替代主流J2EE技术方面的大量工作,其中大部分是在开源领域进行的。很多这些工作都是对主流J2EE世界中复杂性的反应,但也有很多是在探索替代方案并提出创新想法。一个常见的问题是如何将不同的元素连接在一起:当这些元素是由不同的团队在彼此之间了解甚少的情况下构建时,如何将这个web控制器架构和那个数据库接口连接在一起。一些框架已经尝试解决这个问题,并且有几个正在扩展以提供从不同层组装组件的通用功能。这些通常被称为轻量级容器,例如PicoContainer和Spring。

Underlying these containers are a number of interesting design principles, things that go beyond both these specific containers and indeed the Java platform. Here I want to start exploring some of these principles. The examples I use are in Java, but like most of my writing the principles are equally applicable to other OO environments, particularly .NET.

这些容器的基础是一些有趣的设计原则,超越了这些具体容器和Java平台。在这里,我想开始探索其中一些原则。我在示例中使用的是Java,但和我的大部分写作一样,这些原则同样适用于其他面向对象的环境,尤其是.NET。

Components and Services

组件和服务

The topic of wiring elements together drags me almost immediately into the knotty terminology problems that surround the terms service and component. You find long and contradictory articles on the definition of these things with ease. For my purposes here are my current uses of these overloaded terms.

有关如何将元素连接在一起的主题几乎立刻让我陷入了围绕服务和组件术语的复杂问题,关于这些的定义,你会很容易得找到长且充满矛盾的文章,下面是我关于这些术语的定义。

I use component to mean a glob of software that's intended to be used, without change, by an application that is out of the control of the writers of the component. By 'without change' I mean that the using application doesn't change the source code of the components, although they may alter the component's behavior by extending it in ways allowed by the component writers.

我是用组件来表示被应用程序使用,无需改变的软件,而该应用程序超出了组件编写者的控制。通过无需改变,我指的是应用程序不改变组件源码,尽管可能通过继承组件的方式更改组件的行为,前提是这样的扩展是组件编写者允许的。

A service is similar to a component in that it's used by foreign applications. The main difference is that I expect a component to be used locally (think jar file, assembly, dll, or a source import). A service will be used remotely through some remote interface, either synchronous or asynchronous (eg web service, messaging system, RPC, or socket.)

服务跟组件很相似,他们都是被外部应用程序使用的。主要的不同是我希望组件是在本地使用(比如jar包,assembly,dll 或者源码导入等)。而服务将通过某些远程接口进行同步或者异步的调用(比如 web 服务,消息系统,RPC 或者 socket等)

I mostly use service in this article, but much of the same logic can be applied to local components too. Indeed often you need some kind of local component framework to easily access a remote service. But writing "component or service" is tiring to read and write, and services are much more fashionable at the moment.

在本文我主要使用服务,但是相同逻辑也可以用在本地组件。实际上你经常需要一种本地组件框架来方便的访问远程服务。但是写“组件和服务”会很繁琐,并且当下服务一词更为时髦。

3. Techniques/Tips 分享一个小技巧

lambda 中 flatmap 和 map 的区别是 flatmap 会将多个流的数据打平处理,参数为流,返回值也是流,在处理 Optional 时使用 flatmap 可以直接处理 Optinal 包裹的值,而直接使用 map,处理的则是 Optional,要更为简便

4. Share 分享一个观点

本周学习了郑晔的软件设计之美,其中对于函数式编程有了更为深入的了解,函数式编程核心是组合性和不变性,函数是一等公民,所谓一等公民是指:

  • 可以被按需创建
  • 可以被存储
  • 可以被当做参数传递
  • 可以被当做返回值返回

函数式编程鼻祖为 LISP(List Processing),可以看到主要是关于列表处理的语言,通过七个算子可以实现列表元素的各种转换,其中最重要的是 mapfilterreduce,通过这三种操作基本可以实现列表的各种操作

Java 中我们在没有 lambda 之前是通过匿名内部类来模拟实现函数的,有了 lambda,Java 也可以实现函数式编程

函数式编程还有以下好处:

  • 惰性求值
  • 无限流
  • 记忆
  • Optional

在后续的工作中,可以尝试将 for 转换为 lambda 进行编程