如果我们使用工厂模式,我们应该对用户隐藏产品吗?
If we are using Factory Pattern should we hide products from user?
假设我有一个 AnimalFactory
class,它产生 Dog, Cat
和 Fish
。
使用 AnimalFactory
使事情变得异常简单,一切都很好。
我的问题是,是否有规则或良好做法 建议我们隐藏 Dog、Cat 和 Fish,以免被直接使用?我的意思是 Dog myDog = new Dog();
将在代码中被禁止。
如果有,如何正确隐藏?
是的,如果你的对象应该只通过工厂创建,你应该尽量避免有人跳过这条规则的可能性。
在 c# 中,如果 Dog、Cat 和 Fish 的消费者在不同的程序集上,您可以将构造函数设为内部,这样只有与 "animals" 在同一程序集中实现的工厂可以创建它们。
我确定 java 中有类似的内容。
这完全取决于消费者是否需要关心狗或猫,或者他们是否只关心一些动物?
也就是说,如果 Animal.Speak() 没问题,那么只暴露动物,让消费者不知道实现细节。但是,如果有 Dog 特有的东西,例如 Dog.BarkAtMoon(),那么您必须了解它的使用方式。
此外,您可能喜欢依赖接口,例如 IAnimal。然后你有 class Dog : IAnimal 和你的工厂 returns IAnimals。通过这种方式,消费者对实现的了解更少,并且只有界面。
也许你会有
class AnimalFactory
{
IAnimal GetAnimal(AnimalTypeEnum type) { ... return IAnimal type requested ... }
Dog GetDog(string name) { ... just give me a dog named "name" (or IDog) ... }
}
除了指出接口方面的其他答案外,如果需要以某种方式构造复杂对象,并且您想在一个地方(即工厂)强制执行该要求,工厂模式也很有用。在这种情况下,根据您的问题,最好还保护任何其他构造该对象的方法。
回答你的问题,是的。请允许我详细说明 -
当我们像Dog myDog = new Dog();
这样直接实例化对象时,我们编写了一个依赖项。
现在假设,您希望为实例化 Dog 的函数编写单元测试用例,您将没有机会用模拟 Dog 对象替换实际的狗对象。因此,我们坚持使用接口并从外部提供依赖项。
如果我想强制使用接口并阻止使用 new
运算符,我可以进行以下设置 -
接口程序集 - 这将定义 public interface IDog
用于具体实现的程序集 - 这是有 internal class Dog
和一个 public class Factory
的 Create
函数将 return IDog
客户端程序集 - 这里 Dog
将不可访问,因此客户端创建 dog 实例的唯一方法是通过工厂 return IDog
像这样 IDog dog = factory.Create();
为了传达我的观点,我将设置保持得非常简单
依赖倒置原则告诉我们客户端classes应该避免依赖具体的实现。工厂模式通过将客户端与创建逻辑屏蔽开来促进了这一点,并且客户端将使用一个接口而不是一些具体的 class。使具体 classes 包的构造函数成为本地而不是 public 可能是一种好方法。
假设我有一个 AnimalFactory
class,它产生 Dog, Cat
和 Fish
。
使用 AnimalFactory
使事情变得异常简单,一切都很好。
我的问题是,是否有规则或良好做法 建议我们隐藏 Dog、Cat 和 Fish,以免被直接使用?我的意思是 Dog myDog = new Dog();
将在代码中被禁止。
如果有,如何正确隐藏?
是的,如果你的对象应该只通过工厂创建,你应该尽量避免有人跳过这条规则的可能性。
在 c# 中,如果 Dog、Cat 和 Fish 的消费者在不同的程序集上,您可以将构造函数设为内部,这样只有与 "animals" 在同一程序集中实现的工厂可以创建它们。
我确定 java 中有类似的内容。
这完全取决于消费者是否需要关心狗或猫,或者他们是否只关心一些动物?
也就是说,如果 Animal.Speak() 没问题,那么只暴露动物,让消费者不知道实现细节。但是,如果有 Dog 特有的东西,例如 Dog.BarkAtMoon(),那么您必须了解它的使用方式。
此外,您可能喜欢依赖接口,例如 IAnimal。然后你有 class Dog : IAnimal 和你的工厂 returns IAnimals。通过这种方式,消费者对实现的了解更少,并且只有界面。
也许你会有
class AnimalFactory
{
IAnimal GetAnimal(AnimalTypeEnum type) { ... return IAnimal type requested ... }
Dog GetDog(string name) { ... just give me a dog named "name" (or IDog) ... }
}
除了指出接口方面的其他答案外,如果需要以某种方式构造复杂对象,并且您想在一个地方(即工厂)强制执行该要求,工厂模式也很有用。在这种情况下,根据您的问题,最好还保护任何其他构造该对象的方法。
回答你的问题,是的。请允许我详细说明 -
当我们像Dog myDog = new Dog();
这样直接实例化对象时,我们编写了一个依赖项。
现在假设,您希望为实例化 Dog 的函数编写单元测试用例,您将没有机会用模拟 Dog 对象替换实际的狗对象。因此,我们坚持使用接口并从外部提供依赖项。
如果我想强制使用接口并阻止使用 new
运算符,我可以进行以下设置 -
接口程序集 - 这将定义
public interface IDog
用于具体实现的程序集 - 这是有
internal class Dog
和一个public class Factory
的Create
函数将 returnIDog
客户端程序集 - 这里
Dog
将不可访问,因此客户端创建 dog 实例的唯一方法是通过工厂 returnIDog
像这样IDog dog = factory.Create();
为了传达我的观点,我将设置保持得非常简单
依赖倒置原则告诉我们客户端classes应该避免依赖具体的实现。工厂模式通过将客户端与创建逻辑屏蔽开来促进了这一点,并且客户端将使用一个接口而不是一些具体的 class。使具体 classes 包的构造函数成为本地而不是 public 可能是一种好方法。