Typescript-开闭原理

Typescript-开闭原理,typescript,abstract,solid-principles,open-closed-principle,Typescript,Abstract,Solid Principles,Open Closed Principle,我想在我的“小”项目中使用OCP规则。实际上,我在实现这一点时遇到了一个问题。让我给你看看我写了什么 abstract class AnimationType { public abstract createAnimation(timing: number): { in: string, out: string }; } class FadingAnimation extends AnimationType { public createAnimation(timing: numb

我想在我的“小”项目中使用OCP规则。实际上,我在实现这一点时遇到了一个问题。让我给你看看我写了什么

abstract class AnimationType {
    public abstract createAnimation(timing: number): { in: string, out: string };
}

class FadingAnimation extends AnimationType {
  public createAnimation(timing: number): { in: string, out: string } {
    return { in: 'opacity: 0', out: 'opacity: 1' }
  }
}

class TransformAnimation extends AnimationType {
  public createAnimation(timing: number): { in: string, out: string } {
    return { in: 'transform: translateX(-100%)', out: 'transform: translateX(100%)' }
  }
}

class AnimationCreator {
  private timing: number;

  constructor(time: number) {
    this.timing = time;
  }

  getAnimation(animation: AnimationType): { in: string, out: string } {
    return animation.createAnimation(this.timing);
  }
}

我写得好吗?如果我这样做了,那么我实际上得到了什么?如果我想添加这个动画,我需要发送FadingAnimation类的对象。如果我想要变换动画,我需要发送TransformAnimation类的对象-所以我必须在某个地方使用switch(this.animationType)。

我同意Aluan Haddad的观点。不要在这里用简单的JAVA模式思考。尽管Typescript看起来很像C#,因此甚至有点像JAVA,但它最终还是JavaScript。继承规则,正如您从JAVA中了解到的,在这里并不深入。不要试图建立复杂的继承模式或相关的设计原则。使用Typescript,您必须调整编码方式

解决您的问题的一个好方法是使用一个普通服务和两个返回所需对象的方法

e、 g


上面的代码实际上不需要面向对象<代码>动画类型类没有状态,不能从多个实例中获益,因此不需要。除非类实例与TransformAnimation的
animation instanceof区别开来(这不是用开闭原则应该做的事情),否则这些类是没有用的

AnimationType
类可替换为函数方法:

interface IAnimation {
  type?: string;
  in: string;
  out: string;
}

type TAnimationFactory = (timing: number) => IAnimation;

const createFadeAnimation: TAnimationFactory = (timing: number) => {
   return { in: 'opacity: 0', out: 'opacity: 1' };
}

class AnimationCreator {
  private timing: number;

  constructor(time: number) {
    this.timing = time;
  }

  getAnimation(animationFactory: TAnimationFactory): IAnimation {
    return animationFactory(this.timing);
  }
}
根据
AnimationCreator
的功能,它也可以被函数替换,也可以被取消,以便直接使用动画工厂函数


如果
AnimationType
是有状态的,例如它接受transform%作为构造函数参数,则这可能会更改。但在这种情况下,不清楚为什么
变换
属性应被视为与
定时
不同的类型-两者都可能因动画而异,因此在构建时定义。在这种情况下,
AnimationCreator
不需要
计时
,因此它是无状态的,其目的变得不明确。

原则和模式在语言之间是绝对可转换的。当您跨越范例的边界时,它们可能不太适用。坚实的原则和OOP模式适用于任何面向对象,而不仅仅是Java

记住,TypeScript/JavaScript不仅仅是面向对象的

从一个问题开始 问题不在于你试图从其他语言的原则中吸取教训。这里的问题是,您试图从原则开始

好的代码设计,不管你使用什么样的范例,都是从你想要解决的问题开始的。在寻找模式或应用原则之前编写更多的代码,这样随着应用程序的增长,设计可以从您发现的实际问题中浮现出来

从一个原则开始,你过早地决定问题最终可能是什么;您的设计可能会使您远离干净代码的目标

模式和原则是高度可转移的,但要等待有问题的信号,而不是过早地应用某种解决方案

简单更好 在你的情况下,你可以用最简单的方法解决问题。如果您有一个测试来指导您,那么您可以在以后轻松地更新实现细节

也许在您的情况下,一个简单的字典/对象就足够了

const animationType = {
    fading: {
        in: 'opacity: 0',
        out: 'opacity: 1'
    },
    transforming: {
        in: 'transform: translateX(-100%)',
        out: 'transform: translateX(100%)'
    }
};
如果您不想强制执行
淡入
转换
,您可以键入此项以允许任何键,但您还不需要添加此灵活性:

interface AnimationTypes {
    [key: string]: { in: string, out: string };
}

对于TypeScript代码的质量来说,可能最糟糕的事情就是应用源于Java的模式。这段代码应该是面向对象的吗?AnimationType没有状态,它作为类的目的是什么?实际上,它也可以是接口。我想,只是想在你实现OCP的时候实现它。不知道你得到了什么。可能是无用的抽象。也可以键入函数。除非您打算将类实例与TransformAnimation的
动画实例区分开来(这是您不想用OCP做的事情),否则类是没有用的。。所以实际上我不应该在打字脚本中使用OCP,是吗?是的,这是我的建议。代码越复杂,很快就会陷入困境。两年前,我也从爪哇来,走了同样的漫长道路。您必须习惯服务,这是您的选择。谢谢,但我在哪里可以使用OCP?你知道在TS中使用它的好例子吗?看看你的商务级打印机。你不依赖于“超级打印机586”,你只需要使用抽象概念“打印机”。这使得添加“超级打印机和订书机593”成为可能,它可以打印和订书。令人惊叹的。你没有改变原来的打印机,它仍然可以用来打印东西。您没有更改原始打印机,也没有更改打印机的抽象概念,但您已经对其进行了扩展。我希望我没有夸大这个比喻。
interface AnimationTypes {
    [key: string]: { in: string, out: string };
}