GoF Factory的命名约定?
此模式使用抽象工厂,然后是工厂的实现。
我确信这两个类有一个标准的命名约定,但我不知道它是什么。
例如:
public abstract class ChocolateFactory { };
public class MyChocolateFactory { } : ChocolateFactory
这里的标准惯例是什么?
我正在考虑ChocolateFactoryBase或ConcreteChocolateFactory,但也许还有别的东西(很像Enum往往以Enum为后缀,例如PetTypeEnum
这样你就可以做PetTypeEnum PetType;
希望这不是主观的。
问题和答案
好的,这个问题始于抽象工厂的命名问题。 根据经验,总是使用你正在做的“正式”名称(例如工厂,装饰师等)和具体实现的描述(例如士力架,火星,MotifWidget等等)。
所以基本上,你创建一个MSSQLConnection
,它是你描述的具体事物,而Factory
意味着它遵循工厂模式的特征。
好的,到目前为止命名和原始问题。 现在为酷的东西。 讨论是在C#中实现抽象工厂的最佳方式,这是一个不同的主题。 我在C#中实现了所有设计模式的相当多的工作,我将在这里分享一些关于工厂的细节。 开始:
抽象的工厂和工厂
抽象工厂基本上是基类或接口的组合,以及具体的实现。 如果您共享大量代码,则需要基类,如果不共享,则使用接口。
我通常会区分“工厂”和“抽象工厂”。 工厂是创建对象(某种类型)的东西,“抽象工厂”是创建任意类型对象的东西。 因此, 抽象工厂的实现是工厂 。 这与下一条信息相关。
工厂模式
支持RTTI的语言能够实现工厂模式。 工厂模式是创建对象的东西。 最简单的实现是一个只包含创建对象的方法的类,例如:
// ... public void CreateConnection() { return new SqlConnection(); } // ...
你通常用这个来抽象东西。 例如,生成XML节点的HTML解析器中的内容会根据HTML标记创建特定类型的节点。
工厂通常根据运行时信息做出决策。 因此可以概括Factory模式来实现以下内容:
public T Create(string name) { // lookup constructor, invoke. }
使用RTTI创建通用工厂模式非常容易,RTTI为每个名称存储一个Type
。 查找名称,使用reflection创建对象。 完成。
哦,作为奖励,你必须编写比手工制作所有工厂更少的代码。 因为所有实现都是相同的,所以您可以将它放在基类中并在静态构造函数中填充Dictionary。
概括抽象工厂
抽象工厂基本上是工厂的集合,它们以与Factory模式相同的方式创建对象。 唯一共享的是接口(例如Create或者您可以使用inheritance来创建抽象)。
实施是非常微不足道的,所以我就把它留在那里。
解耦工厂和类型
让我们回到GoF示例。 他们谈论MotifFactory
和PMFactory
。 在未来,我们将遇到另一个UI thingie,我们需要一个ASPNETFactory
或SilverlightFactory
。 然而,未来是未知的,如果我们不需要,我们宁愿不发送旧的DLL – 毕竟,这不灵活。
如果我们想为工厂添加新方法,则会产生第二个问题。 因此,这样做将涉及改变所有工厂。 你可能已经猜到了,我不想在多个地方改变它。
幸运的是,我们可以解决这两个问题。 界面是相同的(甚至可以推广),因此我们可以在运行时简单地向工厂添加新function。
我们可以使用属性来告诉类它应该由某个工厂实现,而不是告诉工厂要创建的对象。 我们还可以在assembly过程中扫描所有类型,因此如果装载了assembly,我们可以简单地即时构建新工厂。
我为此牺牲的是编译时检查,但因为Factory模式通常使用运行时信息,所以这不一定是个问题。
把它全部包装起来,这是我工厂的代码:
/// /// This attribute is used to tag classes, enabling them to be constructed by a Factory class. See the /// class for details. /// /// /// /// It is okay to mark classes with multiple FactoryClass attributes, even when using different keys or different factories. /// /// /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public class FactoryClassAttribute : Attribute { /// /// This marks a class as eligible for construction by the specified factory type. /// /// /// [FactoryClass("ScrollBar", typeof(MotifFactory))] /// public class MotifScrollBar : IControl { } /// /// The key used to construct the object /// The type of the factory class public FactoryClassAttribute(object key, Type factoryType) { if ((factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(Factory<,>)) || factoryType.IsAbstract || factoryType.IsInterface) { throw new NotSupportedException("Incorrect factory type: you cannot use GenericFactory or an abstract type as factory."); } this.Key = key; this.FactoryType = factoryType; } /// /// The key used to construct the object when calling the method. /// public object Key { get; private set; } /// /// The type of the factory class /// public Type FactoryType { get; private set; } } /// /// Provides an interface for creating related or dependent objects. /// /// /// /// This class is an implementation of the Factory pattern. Your factory class should inherit this Factory class and /// you should use the [ ] attribute on the objects that are created by the factory. /// The implementation assumes all created objects share the same constructor signature (which is not checked by the Factory). /// All implementations also share the same type and are stored by key. During runtime, you can /// use the Factory class implementation to build objects of the correct type. /// /// /// The Abstract Factory pattern can be implemented by adding a base Factory class with multiple factory classes that inherit from /// the base class and are used for registration. (See below for a complete code example). /// /// /// Implementation of the Strategy pattern can be done by using the Factory pattern and making the /// implementations algorithms. When using the Strategy pattern, you still need to have some logic that picks when to use which key. /// In some cases it can be useful to use the Factory overload with the type conversion to map keys on other keys. When implementing /// the strategy pattern, it is possible to use this overload to determine which algorithm to use. /// /// /// The type of the key to use for looking up the correct object type /// The base interface that all classes created by the Factory share /// /// The factory class automatically hooks to all loaded assemblies by the current AppDomain. All classes tagged with the FactoryClass /// are automatically registered. /// /// /// /// // Create the scrollbar and register it to the factory of the Motif system /// [FactoryClass("ScrollBar", typeof(MotifFactory))] /// public class MotifScrollBar : IControl { } /// /// // [...] add other classes tagged with the FactoryClass attribute here... /// /// public abstract class WidgetFactory : Factory<string, IControl> /// { /// public IControl CreateScrollBar() { return Create("ScrollBar") as IScrollBar; } /// } /// /// public class MotifFactory : WidgetFactory { } /// public class PMFactory : WidgetFactory { } /// /// // [...] use the factory to create a scrollbar /// /// WidgetFactory widgetFactory = new MotifFactory(); /// var scrollbar = widgetFactory.CreateScrollBar(); // this is a MotifScrollbar intance ///
/// public abstract class Factory : IFactory where Intf : class { /// /// Creates a factory by mapping the keys of the create method to the keys in the FactoryClass attributes. /// protected Factory() : this((a) => (a)) { } /// /// Creates a factory by using a custom mapping function that defines the mapping of keys from the Create /// method, to the keys in the FactoryClass attributes. /// /// A function that maps keys passed to to keys used with [ ] protected Factory(Func typeConversion) { this.typeConversion = typeConversion; } private Func typeConversion; private static object lockObject = new object(); private static Dictionary> dict = null; /// /// Creates an instance a class registered with the attribute by looking up the key. /// /// The key used to lookup the attribute. The key is first converted using the typeConversion function passed /// to the constructor if this was defined. /// An instance of the factory class public virtual Intf Create(Key key) { Dictionary> dict = Init(); Dictionary
我不知道这里有什么约定,但我认为这在很大程度上取决于具体情况。 我只在Dependency注入方案中使用AbstractFactory,我想在运行时创建类型,我必须提供抽象。
- “抽象”部分可以是一个界面 – >“公约”将是“ 我的名字大全”
- 你的基类应该描述关于它的实现的“常见”事情,信息位于上下文中:如果在你的上下文中,ChocolateFactory可能是一个“抽象”概念,那么实现(应该描述具体的东西(MyChocolateFactory不是一个好名字大全)) )应该显示他们(是)的关系,但也应该显示具体的用例。
- 关于您的评论:如果不需要任何其他工厂实施只是为了将来可能的用例,请不要使用抽象工厂;)
你可以使用这样的东西:
// general interface for abstract factory (this is optional) public abstract class AbstractFactory { }; // interface that uses a type of factory and produce abstract product public abstract class AbstractChocolateFactory : AbstractFactory { }; // family of concrete factories that produce concrete products public class NestleChocolateFactory { } : AbstractChocolateFactory public class SwissChocolateFactory { } : AbstractChocolateFactory
这只是一个想法,但使用抽象工厂模式的实现完全取决于您具有的具体任务。
上述就是C#学习教程:GoF Factory的命名约定?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1009649.html