美文网首页
service层和model层应该全部使用静态类吗?

service层和model层应该全部使用静态类吗?

作者: Abin_ | 来源:发表于2019-10-05 12:48 被阅读0次

    静态类,即整个类全部使用静态方法。好处自然是不用讲,可以不用实例化。直接使用类名::方法调用。而实例化方法,必须先实例化(new)方可调用。除此,静态方法在加载类的时候,就已经加载到内存(PS:有说其实实例方法也是编译阶段就加到内存,并无区别),并且有仅有一份,具有比实例方法更高的效率。而实例方法,必须先实例化,每个实例都是一个副本。每创建一个实例都是不小的开销。看到此处,似乎静态类拥有比实例类更实用和高效。其实这已经是我第二次在企业级项目中使用laravel框架中看全局使用静态类。

    关于这个问题,我也是通过segmentfault、Google、stackoverflow等渠道找了很多观点。发现确实存在争议。有人认为不应被OOP的思想固化,怎么简单怎么来。有的则认为应该用好OOP的思想,静态类在面向对象世界中就是一个异类,不应该存在。

    思考再三并结合这么多年的编程实践。我决定就此议题直接抛出自己的一些观点。希望有更深刻认识的同行能给予指导。

    • 首先,PHP是一个混合型语言,不是一个真正的面向对象的语言。可以使用OOP,也可以使用传统的过程化编程。而不像C++、java等与生俱来就是OOP语言。有统一的入口方法,必须使用严格的面向对象和规范的方式才能正确运行程序。

    • 其次,PHP生命周期是基于请求的。一次请求到响应就是完整的生命周期。不具备java等语言的内存常驻和多线程特性。FPM进程模型下,每个请求是彼此独立的进程,在内存上是隔离的。所以静态方法也不存在线程安全问题。因而尽管在PHP项目中大胆的使用静态类,在一次请求业务中, 静态方法中不出现静态属性或全局变量,即使多次调用,一般也不会出现问题。

    • 在初学OOP编程的时候总是会以人类和实例化的某个人作为例子。可以很好的区分出类和对象。但在编程实践中,以不同的角度看问题总是能提炼出不同的模型和解决方案。所以很多时候使用静态类和实例类是存在争议的。

    • 面向对象编程思维,实例化方法的提出不是为了解决性能问题。而是为了使项目更具工程化。

    • 静态方法是属于整个类的,实例方法是属于对象的。理论上如果一个方法是属于类的就不应该设计成实例方法,相反如果一个方法是属于对象的就不应该设计为静态方法。

    • 静态方法有很大的局限性。会失去继承、多态的特性,破坏封装。无法调用实例方法,使用实例属性。

    • 静态方法是面向过程的编程思维,应该避免过多使用。对于一些无状态、没有复杂多变的业务逻辑。类似助手类、工具类可以使用静态类。

    • 静态方法无法明确依赖关系,静态调用的面向过程的代码会加重类之间的耦合。需要使用实例化对象声明依赖关系。传统的new实例化方式也是一种重耦合。因而PHP几次革命从传统的include+new实例化到new实例化,使用autoload自动包含。到现代使用命名空间、 spl_autoload_register 加上 IOC容器,依赖注入等方式已经将代码解耦提升到一个新高度。也是现代流行框架(laravel、spring)所推崇的。

    • 最后,个人认为无论项目大小,项目分层如何。应当优先考虑使用实例方法,而不是静态方法。这应该是一种约定。以Laravel为例,可以使用依赖自动注入将service类实例注入控制器方法。更进一步,可以为每个service类定制一个interface契约。在服务提供者,可以将interface和实现类进行绑定。依赖注入interface,将自动解决并实例化绑定的实现类。实现controller和service的解耦以及service类的扩展可替换,体现了OOP 的接口隔离、依赖倒置、开闭原则。同时,如果深入看laravel,可以发现很多地方用到的静态方法调用,其实是使用了一种门面(Facade)设计模式进行代理。最终也是调用了实例方法,此处就不展开。

    • 当然,在工作中,你要先学会生存。我建议你应该服从一个团队的规范,尽管技术规范和主观上不合理的编程风格限制会让你感到不适。当你拥有足够的话语权和影响力的时候再去坚持自己的观点。

    相关文章

      网友评论

          本文标题:service层和model层应该全部使用静态类吗?

          本文链接:https://www.haomeiwen.com/subject/xwmspctx.html