如何为整个服务提供一个单例实例?
How to make availabe a singleton instace to all over the service?
这就是我实现单例的方式class
import { AClient } from 'libbrary'
import { Container, Service } from 'typedi';
@Service()
class MyClass {
private client: AClient;
static getInstance(): MyClass {
return Container.get(MyClass);
}
getClient(): AClient {
if(this.client !== null){
return this.client;
}
this.client = new AClient();
return this.client;
}
}
这里重点是使用Acliet()。
我正在通过以下方式实现此客户端的方法。
class AClientMethodsImplementation {
async getSomeData() {
// I need client here so that I can use client.get()
}
}
现在我应该在我的服务中使用这些方法。
class NeedDataHere {
// Not only here, in the entire project I need this many places.
// should I create AClientMethodsImplementation() instance everytime?
// If that is the case what is the point of a singleton?
// How to achieve this? What is the correct approach?
}
我的方法是否正确?或者处理这种情况的最佳方法是什么?
我说这是一个问题,因为我观察到每次通过创建新的 AClientMethodsImplementation
class 来点击 getSomeData() 都会给出相同的结果,即使我将输入数据更改为该函数。我怀疑它在某处缓存。
这真的取决于你的场景。如果 AClientMethodsImplementation
是无状态的(它不会在方法调用之间保存实例相关数据)你应该声明它的所有成员 static
:
class AClientMethodsImplementation {
static async getSomeData() {
AClient client = MyClass.getInstance().getClient();
}
}
class NeedDataHere {
// Call static methods
let data = AClientMethodsImplementation.getSomeData();
}
如果 AClientMethodsImplementation
应该存储与实例相关的数据,您当然必须创建一个新实例(除了特定方法不会改变实例。在这种情况下,它可以是 static
).
如果您希望此实例在整个应用程序中是相同的,那么您可以将 AClientMethodsImplementation
实现为单例。
Singleton 模式的首选替代方案是使用依赖注入(IoC 模式的一种实现)。这样您就可以共享同一个实例,但不会牺牲松耦合和可测试性。
通常,当您想在全局范围内使用单个对象状态时,您会使用共享实例(通过依赖注入或单例),例如像 cookie 一样的会话对象。另一个用例是,由于资源分配或实例化太耗时,实例化可能过于昂贵。然后,您分配一次资源,例如 database/service 连接并重用它(共享资源)。另一个用例是提供对共享资源的受控访问,例如数据缓存。例如,您通常在整个应用程序中使用共享记录器实例。
检查您的代码时,共享 AClient
实例的好处可能是提高性能。如果您可以说客户端公开了昂贵的共享资源或数据,或者创建它的多个实例通常过于昂贵,那么共享实例是值得的。显然,您仍然创建 AClientMethodsImplementation
的多个实例这一事实不会使共享实例变得多余。
这就是我实现单例的方式class
import { AClient } from 'libbrary'
import { Container, Service } from 'typedi';
@Service()
class MyClass {
private client: AClient;
static getInstance(): MyClass {
return Container.get(MyClass);
}
getClient(): AClient {
if(this.client !== null){
return this.client;
}
this.client = new AClient();
return this.client;
}
}
这里重点是使用Acliet()。
我正在通过以下方式实现此客户端的方法。
class AClientMethodsImplementation {
async getSomeData() {
// I need client here so that I can use client.get()
}
}
现在我应该在我的服务中使用这些方法。
class NeedDataHere {
// Not only here, in the entire project I need this many places.
// should I create AClientMethodsImplementation() instance everytime?
// If that is the case what is the point of a singleton?
// How to achieve this? What is the correct approach?
}
我的方法是否正确?或者处理这种情况的最佳方法是什么?
我说这是一个问题,因为我观察到每次通过创建新的 AClientMethodsImplementation
class 来点击 getSomeData() 都会给出相同的结果,即使我将输入数据更改为该函数。我怀疑它在某处缓存。
这真的取决于你的场景。如果 AClientMethodsImplementation
是无状态的(它不会在方法调用之间保存实例相关数据)你应该声明它的所有成员 static
:
class AClientMethodsImplementation {
static async getSomeData() {
AClient client = MyClass.getInstance().getClient();
}
}
class NeedDataHere {
// Call static methods
let data = AClientMethodsImplementation.getSomeData();
}
如果 AClientMethodsImplementation
应该存储与实例相关的数据,您当然必须创建一个新实例(除了特定方法不会改变实例。在这种情况下,它可以是 static
).
如果您希望此实例在整个应用程序中是相同的,那么您可以将 AClientMethodsImplementation
实现为单例。
Singleton 模式的首选替代方案是使用依赖注入(IoC 模式的一种实现)。这样您就可以共享同一个实例,但不会牺牲松耦合和可测试性。
通常,当您想在全局范围内使用单个对象状态时,您会使用共享实例(通过依赖注入或单例),例如像 cookie 一样的会话对象。另一个用例是,由于资源分配或实例化太耗时,实例化可能过于昂贵。然后,您分配一次资源,例如 database/service 连接并重用它(共享资源)。另一个用例是提供对共享资源的受控访问,例如数据缓存。例如,您通常在整个应用程序中使用共享记录器实例。
检查您的代码时,共享 AClient
实例的好处可能是提高性能。如果您可以说客户端公开了昂贵的共享资源或数据,或者创建它的多个实例通常过于昂贵,那么共享实例是值得的。显然,您仍然创建 AClientMethodsImplementation
的多个实例这一事实不会使共享实例变得多余。