我是一名初学程序员。我知道OOP的基础知识,但我不知道"最佳实践"还没。例如,一个继续出现在编程中的范例是"抽象工厂"设计模式,看起来相当简单。其背后的关键意图之一是避免使用关键字" new",因为它被认为是有害的。我在编程课程中从未听过这个。有人可以详细阐述这一点吗?为什么我们要避免以这种形式实例化对象?
答案 0 :(得分:9)
在您编写的客户端/调用者类中考虑:
Vehicle v = new Car("BMW");
如果您的代码与上面的代码类似,您将始终获得一辆汽车。将来,如果你真的想要一架飞机,你将不得不更新客户代码。
或者,您使用工厂模式,您的代码如下:
Vehicle v = Factory.getVehicle();
现在,您可以保持从客户端离开车辆(松耦合)的逻辑,如果您必须更新您获得的最终车辆,您的客户将永远不需要更改。只有Factory实施将更新,您的客户将按原样运行。
答案 1 :(得分:4)
我不会说new
被认为是有害的。抽象工厂模式尝试做的是解决new
不可重写的问题(即与虚拟调度不兼容,至少在Java和C#等语言中)。
考虑这个示例代码(C#):
class Sender
{
private ISendChannel channel;
public Sender()
{
}
public void Connect(Uri endpointAddress)
{
// !! Sender is tightly coupled to TCP implementation
// !! even though it doesn't apparently have to be.
this.channel = new TcpSendChannel(endpointAddress);
}
/* ... */
}
在此代码中,我们有一个基接口ISendChannel
,允许向某个端点进行前向通信。但是,给定的实现被固定为始终使用TCP信道,无论如何。这是不可取的,因为现在如果您想要HTTP发送者,您必须修改Sender
类或向其添加新方法。这是“坏耦合”。
相反,您可以使用工厂创建频道并将其传递给发件人。发件人将要求工厂创建频道,从而放弃该责任。新的实现可能如下所示:
class Sender
{
private readonly ISendChannelFactory factory;
private ISendChannel channel;
public Sender(ISendChannelFactory factory)
{
this.factory = factory;
}
public void Connect(Uri endpointAddress)
{
// Sender does not have to care what type of channel it is.
this.channel = this.factory.CreateSendChannel(endpointAddress);
}
/* ... */
}
现在要使用HTTP通道,您可以使用不同的工厂类型实例化发件人,例如new Sender(new HttpSendChannelFactory(/* ... */));
。然后,HttpSendChannelFactory
可以从HttpSendChannel
方法返回ISendChannel
(来自CreateSendChannel
的具体类型)。
答案 2 :(得分:4)
我建议您阅读这篇文章:http://www.codinghorror.com/blog/2005/09/head-first-design-patterns.html
关键部分是:学习编写简单代码的最好方法是编写简单的代码!应该避免使用各种复杂形式的模式,直到它们是绝对必要的。这是初学者需要学习的第一件事。不是最后一件事。
我同意 - 只有在真的需要它时才需要工厂。
好的,回到主题,关键字new
可能是邪恶的,但在大多数情况下,肯定不是也不应该是令人头疼的问题。看到了
List <Person> persons = new ArrayList<Person>();
完全没问题。甚至不敢考虑工厂生产ArrayList
或LinkedList
。那将是完全过度设计的。
“我见过很多系统,其中Factory模式被过度使用。例如,如果系统中的每个对象都是使用Factory创建的,而不是直接实例化(例如,new StringNode(ノ)) ,该系统可能拥有过多的工厂。“@ Joshua Kerievsky
除非你确定它是个好主意,否则不要过早添加模式,如果没有足够的经验你就无法确定。开始用你脑海中的模式编写代码 - 种类:工厂,这很棒,让我们看看何时可以放置它! - 这不是一个好主意:)。更好的方法是在代码中的地方添加模式很麻烦,当你觉得(气味:) - 代码味道)这可以以某种方式更好地完成。那就是重构模式。
有一本很棒的书,我会给你链接到“将创作知识转移到工厂”这一章
http://www.informit.com/articles/article.aspx?p=1398606&seqNum=2
我知道它很长,但请仔细阅读,这肯定值得付出努力
答案 3 :(得分:1)
要理解这种模式或使用new
关键字有什么问题,您缺少必要的先决条件编程范例Programming against an interface
研究这个,一旦你理解它是什么,你就会明白,真正强制执行/遵循它的唯一方法是避免在你的代码中使用new
,即明确地在你的代码中实例化具体对象令人讨厌的代码耦合效应。
答案 4 :(得分:0)
抽象工厂模式的想法不是要了解包括构造函数在内的具体实现。
因此标准的Factory模式将返回一个具体的类,例如
SomeType SomeVar = SomeFactory.CreateSomeType();
抽象工厂模式将在哪里
SomeInterface SomeVar = AbstractFactory.CreateSomeInterface();
因此,不是SomeType暴露给消费者,而是只有接口。只是更高级别的抽象,这是有用的,但只有在您不希望工厂消费者必须了解SomeType时才有害。
答案 5 :(得分:-1)
据我所知,new关键字没有任何问题。 我正在谈论PHP开发人员。新关键字没有任何问题,也没有一些安全问题。
PHP中的工厂模式用于自动要求,生成类的实例,并返回该类。不是因为new关键字有问题,但是要运行一个静态函数要快得多,然后要求并为你需要的每个对象使用new关键字。
在后台你无论如何都会使用新关键字:)
新的没有错,没有必要避免它。它与工厂模式相比,它更快地获得类实例然后需要类,然后用新关键字实现它。