我有一个TypeScript类,它正在创建ZMQ总线通信的基础。我首先想做一个通用类,可以根据需要实例化许多时间。但是现在,我需要制作更多的实例,这些实例不完全适合我制作的一般类。实际上,唯一的区别是在这些新实例中,从不使用request
方法,具体取决于type
。因此,是否可以保留相同的通用类,但在不需要时忽略request
方法?
let zmq = require("zeromq")
class ZMQBus {
socket:any
port:number
constructor(type:string, port:number) {
this.socket = zmq.socket(type)
this.port = port
}
open(): void {
this.socket.connect("tcp://localhost:" + this.port)
this.socket.on("message", function(reply) {
console.log("Received reply : " + reply.toString());
})
}
request(msg:any): void {
this.socket.send(msg);
}
close(): void {
this.socket.close();
}
}
我知道你说过你想避免两个类,因为你不想暗示这两个类是不同的。该请求在某些情况下不重要,不会使其有害。您仍然可以将单个类与request
的单个实现一起使用,仅在需要时使用它。如果确实需要规定request
不存在,则必须创建一个单独的类型。您可以通过使用工厂模式和条件类型在语义上实现所需的内容,而无需任何反模式]
type ZmqTypes = "REQUEST" | "NOREQUEST"; interface ZMQBus { open: () => void; close: () => void; request?: (msg: any) => void; type: ZmqTypes; port: number; } interface ZMQBusR extends ZMQBus { request: (msg: any) => void; } interface ZMQBusNoR extends Omit<ZMQBus, "request"> {} class GenericZMQBus implements ZMQBus { socket:any port:number constructor(type:string, port:number) { this.socket = zmq.socket(type) this.port = port } open(): void { this.socket.connect("tcp://localhost:" + this.port) this.socket.on("message", function(reply : any) { console.log("Received reply : " + reply.toString()); }) } close(): void { this.socket.close(); } } class ZMQBusWithRequest extends GenericZMQBus implements ZMQBusR { request(msg : any) { console.log(msg); } } function createZMQBus<T extends ZmqTypes>(type: T, port: number) : T extends "REQUEST" ? ZMQBusR : ZMQBusNoR { if (type === "REQUEST") { return new ZMQBusWithRequest(type, port) as unknown as T extends "REQUEST" ? ZMQBusR : ZMQBusNoR; } return new GenericZMQBus(type, port) as unknown as T extends "REQUEST" ? ZMQBusR : ZMQBusNoR; } const zmqObj = createZMQBus("REQUEST", 999); const zmqObj1 = createZMQBus("NOREQUEST", 999); zmqObj.request('hello'); zmqObj1.request('error'); // is an error
您仍然具有使用严格类型系统的多个类和接口,但是创建这些对象的单一方法暗示着一个一致的目的,即使不是一致的实现。并且由于两者都扩展了单个通用接口,因此您可以将任一类型作为单个ZMQType进行传递。您只需要确保在尝试使用
request
方法之前,检查其是否正确存在。
function testZMQImplementation(z: ZMQBus) {
if (z.request) {
z.request('testing')
}
}
testZMQImplementation(zmqObj);
testZMQImplementation(zmqObj1);