Jan 01, 1970
之前的局部:
一位类应有唯有一位的变化的来由
// Bad class UserSettingsService { constructor(user: IUser) { this.user = user; } changeSettings(settings: IUserSettings): void { if (this.isUserValidated()) { // ... } } getUserInfo(): Promise<IUserSettings> { // ... } async isUserValidated(): Promise<boolean> { const userInfo = await this.getUserInfo(); // ... } }
这里例子中,我们是的类在本质区别标有意图上落实操作:它使用强弱文、转变强弱文并考资格证书它。
// Better class UserAuth { constructor(user: IUser) { this.user = user; } getUserInfo(): Promise<IUserSettings> { // ... } async isUserValidated(): boolean { const userInfo = await this.getUserInfo(); // ... } } class UserSettings { constructor(user: IUser) { this.user = user; this.auth = new UserAuth(user); } changeSettings(settings: IUserSettings): void { if (this.auth.isUserValidated()) { // ... } } }
軟件线下实体(类、传感器、方程)应有对壮大好放,但对点窜封禁
// Bad class Product { id: number; name: string[]; price: number; protected constructor(id: number, name: string[], price: number) { this.id = id; this.name = name; this.price = price; } } class Ananas extends Product { constructor(id: number, name: string[], price: number) { super(id, name, price); } } class Banana extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } } class HttpRequestCost { constructor(product: Product) { this.product = product; } getDeliveryCost(): number { if (product instanceOf Ananas) { return requestAnanas(url).then(...); } if (product instanceOf Banana) { return requestBanana(url).then(...); } } } function requestAnanas(url: string): Promise<ICost> { // logic for ananas } function requestBanana(url: string): Promise<ICost> { // logic for bananas }
在这个例子中,题目出在HttpRequestCost
类中,该类的getDeliveryCost
方式中包罗差别范例产物的计较前提,并且咱们对每种范例的产物利用零丁的方式。以是,若是咱们须要增加新范例的产物,咱们应当点窜HttpRequestCost
类,这是不宁静的;咱们能够或许或许或许或许会获得意想不到的成果。
为了防止这类环境,咱们应当在Product
类中建立一个不带完成的笼统方式request
。详细完成将担当类:Ananas 和 Banana。他们会为本身完成这个请求。
HttpRequestCost
将接纳Product
类接口前面的product
参数,当咱们在HttpRequestCost
中通报特定的依靠项时,它已为本身完成了request
方式。
// Better abstract class Product { id: number; name: string[]; price: string; constructor(id: number, name: string[], price: string) { this.id = id; this.name = name; this.price = price; } abstract request(url: string): void; } class Ananas extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } request(url: string): void { // logic for ananas } } class Banana extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } request(url: string): void { // logic for bananas } } class HttpRequestCost { constructor(product: Product) { this.product = product; } request(): Promise<void> { return this.product.request(url).then(...); } }
超类的软件应该能够也许也许也许用其子类的软件代替,而会撕碎巧用欧式。
// Bad class Worker { work(): void {/../} access(): void { console.log('Have an access to closed perimeter'); } } class Programmer extends Worker { createDatabase(): void {/../} } class Seller extends Worker { sale(): void {/../} } class Designer extends Worker { access(): void { throwError('No access'); } }
在此示例中,咱们碰到了Contractor
类的题目。 Designer
、 Programmer
、 Seller
都是Worker,他们担当自父类Worker
。但与此同时,设想师无权进入封锁边境,由于他们是承包商,而不是雇员。咱们重写了access
方式并突破了里氏替代准绳。
这个准绳告知咱们,若是咱们用它的子类(比方Designer
类)替代超类Worker
,功效不应当被粉碎。但若是咱们如许做, Programmer
类的功效将被粉碎 - access
方式将具备来自Designer
类的不测完成。
// Better class Worker { work(): void {/../} } class Employee extends Worker { access(): void { console.log('Have an access to closed perimeter'); } } class Contractor extends Worker { addNewContract(): void {/../} } class Programmer extends Employee { createDatabase(): void {/../} } class Saler extends Employee { sale(): void {/../} } class Designer extends Contractor { makeDesign(): void {/../} }
咱们建立了新的笼统层Employee
和Contractor
,并将access
方式移至Employee
类并界说了详细的完成。若是咱们用子类Contractor
替代Worker
类, Worker
功效将不会被粉碎。