C#的静态工厂方法与构造函数相比有哪些优缺点
作者:芝麻麻雀 发布时间:2022-08-29 21:11:45
最近,在与同事进行协同编程时,我们开始讨论在C#中初始化新对象的最佳方法。我一直是使用构造函数实现,尽管他倾向于静态工程方法。这引起了关于每种类型的利弊的大量来来回回的讨论。
为了说明我所说的内容,这是两个例子:
// Using the constructor
SqlConnection myConnection = new SqlConnection(connectionString);
// Using a static factory method
IDbConnection myConnection = SqlConnection.FromConnectionString(connectionString);
之前我从未考虑过实现这些静态工厂方法,我并自嘲问不了解其内容。自从那以后,我改变了注意,让我们深入探讨其优缺点。
静态工厂方法的优点
无须返回一个新的实例
而构造函数总是返回一个新的对象。
当新对象创建失败时,你不能使用一个缓存的对象或返回 null。特别是在编写库代码时,将来可能会很灵活。
你可以使用方法参考
如果你倾向于以一种实用的方式编写C#,你可能会感激你可以在代码中传递该方法(或正式称为“方法组”)的引用。对比一下:
// Static factory method - the method group can be passed in directly as a function reference
var bars = myFoo.Select(bar.FromFoo)
// Constructors - you have to pass in a lambda that constructs the instance via new.
var bars = myFoo.Select(f => new Bar(f));
这段代码没有功能上的差异,只是代码风格上的一个问题。因此可能不应在决策中过分重视。
你能通过名字了解
对于某些对象,尤其是可以通过多种类似方式构造的对象-能够在构造对象的方式上获益良多。让我们以Color类为例,该类可以通过CMYK和RGB参数构造。
// With constructors
var color = new Color(25, 25, 5, 80);
var color = new Color(100, 150, 50);
// With static factory methods
var color = Color.FromCMYK(25, 25, 5, 80);
var color = Color.FromRGB(100, 150, 50);
与更具描述性的静态工程方法进行对比,除非你知道Color的四个值的构造函数是CMYK,三个值的构造函数是RGB,否则无法通过阅读代码来区别出来。
我认为,如果你有不同的构造对象的方式,尤其是参数彼此相似的方式,有很充分的理由来使用静态工厂方法。
工厂方法可以返回不同的类
new Foo()
总是返回一个Foo
类的一个新的实例,Foo.FromBar
很容易的返回一个IFoo
接口,或者Foo
的一个子类。一个可能与之相关的真实示例:
// This could create an IpV4IpAddress that implements IIpAddress
IIpAddress ipv4Address = IpAddress.FromString("127.0.0.1");
// This could create an IpV6IpAddress that implements IIpAddress
IIpAddress ipv6Address = IpAddress.FromString("2001:0db8:0a0b:12f0:0000:0000:0000:0001")
在提供公共API(例如在库上下文中)时,能够根据输入返回不同的实际类型可能非常有价值。特别是因为这意味着你可以在接口或者基类后面隐藏一些实现细节。
我不确定应用程序代码中的价值是否一样大,你可以在其中控制整个库代码,并使大规模重构变得更加容易。
在构造函数中你不应该做的事情
通常,人们并不期望构造函数除了构造对象之外,还能做其他很多事情。你管你可以在构造函数中执行I/O,数据库访问等操作,但大多数人并不期望这样做。按照惯例,你可以自由的以静态工厂方法执行更多的工作,而无需任何人引起注意。
有些人也不认为你应该在构造函数中抛出异常。也许这取决于语言,但在C#中完全可以,如果要在构造函数中创建非托管资源,请注意一下几点。
静态工厂方法的缺点
在构造函数中不应该做的事情
按照惯例,构造函数通常更简单。当我调用构造函数时,通常不希望它执行I/O或
其他。这使构造函数的构造灵活性大大降低,这既是福也是祸。
意味着更多代码
无论如何,你仍然需要构造函数来实际构造对象。静态工厂方法是更多的代码,而代码是一中责任。它通常不是很复制的代码,并且通常静态工厂方法也不是特别长,因此这可能不是一个很大的缺点。
很难找到
通常,当我尝试构造一个新对象时,我会先寻找构造函数。通过自动完成功能很难找到静态方法,因为他们通常无法与其他静态方法区分开。
我认为静态方法最大的问题是你失去了可发现性。
经过研究和思考之后,我认为我目前的看法是:
你应该始终创建一个构造函数,该构造函数将1:1映射到类内部的字段
如果你需要花很多实践来创建对象(例如IO),或者对缓存对象并重新使用它们感兴趣,请使用静态工厂方法。
如果你需要API稳定(例如用于库开发),请隐藏该构造函数并使用静态工厂方法,因为它为你提供了实现的灵活性.
如果你有多种不同的方法来创建类,请创建静态工厂方法并使用它们,因为它们为你提供了描写性.
来源:https://www.cnblogs.com/sesametech-netcore/p/12360190.html


猜你喜欢
- Spring的出现是为了简化 Java 程序开发,而 SpringBoot 的出现是为了简化 Spring 程序开发.SpringBoot
- 一、安装ElasticsearchElasticsearch下载地址:http://www.elasticsearch.org/downlo
- 介绍本篇给大家带了的是ViewFlipper,它是Android自带的一个多页面管理控件,且可以自动播放! 和ViewPager不同,Vie
- 实现方式和继承方式有什么区别呢?*区别:*继承Thread:线程代码存放在Thread子类run方法中*实现Runnable:线程代码存放在
- Apache的POI项目可以用来处理MS Office文档,codeplex上还有一个它的.net版本。POI项目可创建和维护操作各种基于O
- ViewAndroid所有的控件都是View或者View的子类,它其实表示的就是屏幕上的一块矩形区域,用一个Rect来表示,left,top
- 前言以前我们还需要手写数据库设计文档、现在可以通过引入screw核心包来实现Java 数据库文档一键生成。话不多说、直接上代码演示。支持的数
- 本文为大家分享了java开发环境配置教程,供大家参考,具体内容如下配置环境变量win 7配置(win 10配置在下面):1.安装完成后,右击
- 在servlet中,转发和重定向是由request和response完成的。两者之间的区别请看我之前的文章。那么在springMVC中是如何
- API:接口概念:API(Application Programming Interface),应用程序编程接口,Java API是一本程序
- 本文实例为大家分享了C# Email发送邮件的具体代码,供大家参考,具体内容如下//回执地址 var Receipt = &q
- 概述最近项目上反馈某个重要的定时任务突然不执行了,很头疼,开发环境和测试环境都没有出现过这个问题。定时任务采用的是ScheduledThre
- 一:JDBCTemplate简介Spring为各种持久化技术提供了简单操作的模板和回调API:ORM持久化技术模板类原生JDBCorg.sp
- 1 什么是条件变量condition_variable是一个类,常和mutex搭配使用。condition_variable类是一个同步原语
- 前言不知道你是否参加过拼多多上邀请微信好友砍价功能,这个功能实现首先需要考虑的就是获取微信用户的信息。获取用户信息就是获取公众号下微信用户的
- Android植物大战僵尸小游戏全部内容如下:相关下载:Android植物大战僵尸小游戏具体代码如下所示:package com.examp
- 本节向你展示如何在任务中发送数据给UI线程里的对象,这个特性允许你在后台线程工作,完了在UI线程展示结果。在UI线程定义一个HandlerH
- java 中newInstance()方法和new关键字的区别* 它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新
- springboot + docker + jenkins自动化部署项目,jenkins、mysql、redis都是docker运行的,并且
- 1、MediaCodec调用流程首先,我们先看下MediaCodec::CreateByType函数里面做了什么:sp<MediaCo