“控制反转”在 Lisp 中被广泛使用。这很简单,因为函数和闭包是一流的对象。
依赖注入是微不足道的。类和函数可以通过符号和头等类来配置。
Common Lisp 中通常不需要用于 IoC 或 DI 的“框架”,因为内置了许多用于配置和参数化应用程序和库的功能。
'first class' 表示某些东西可以存储在变量中、作为参数传递或作为结果返回。
在像 Common Lisp 这样的语言中,函数和类是第一类对象。另外,为了通过后期绑定解耦,您可以使用符号作为它们的名称。 Common Lisp 对象系统知道元类和符号作为类的名称。甚至通用函数和方法也是对象并且具有元类。
如果concurrent-secure-server 是一个类,default-response 是一个函数,你可以这样做:
(make-instance 'web-services
:server-class 'concurrent-secure-server
:default-response-function 'default-reponse)
上面使用符号作为类和函数的名称。如果函数获得新版本,Web 服务可能会稍后调用新版本。
或者:
(make-instance 'web-services
:server-class (find-class 'concurrent-secure-server)
:default-response-function #'default-reponse)
在上面的例子中,我们传递了类对象和函数对象。
在 Common Lisp 软件模块中可以有全局变量,你可以用正确的信息来设置:
(defvar *default-server-class* 'concurrent-secure-server)
或者,您可以将它们设置在如下插槽中。
(defclass server-object ()
((default-response-function
:initarg :default-response-function
:initform *server-default-response-function*)))
(defvar *my-server*
(make-instance 'server-object
:default-response-function 'my-default-response-function))
您甚至可以创建对象,然后在配置阶段更改它们的类。
Common Lisp 对象系统允许您更改类并更新现有对象。
如果你创建一个实例,你可以随心所欲:
像这样:
(let ((my-class 'foo-class)
(my-args `(:response-function ',*some-reponse-function)))
(apply #'make-instance my-class my-args))
有时您会看到在运行时计算此类参数列表的 Lisp 库。
您可以在运行时配置 Lisp 应用程序的另一件事是通过泛型函数。通用函数允许 :before、:after 和 :around 方法——它们甚至允许您自己的自定义调用方案。因此,通过使用您自己的从其他类和 mixin 类继承的类,可以重新配置泛型函数。这就像您内置了面向切面编程的基本机制。
对于那些对这些更高级的面向对象概念感兴趣的人,Xerox PARC 提供了一些文献,其中在创建 CLOS 时已经研究了这些问题。当时它被称为“开放式实现”:
http://www2.parc.com/csl/groups/sda/publications.shtml
在开放式实施方法中,模块允许其客户单独控制模块自己的实施策略。这允许客户端定制模块的实现策略以更好地满足他们的需求,有效地使模块更可重用,客户端代码更简单。该控件通过精心设计的辅助界面提供给客户端。
你不需要的东西:XML。 Common Lisp 是它自己的配置语言。例如,可以通过宏来编写扩展以简化配置。可以通过LOAD 轻松加载这些配置。