- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
此模式使用抽象工厂,然后使用工厂的实现。
我确定这两个类有一个标准的命名约定,但我不知道它是什么。
例如:public abstract class ChocolateFactory { };
public class MyChocolateFactory { } : ChocolateFactory
这里的标准约定是什么?
我在考虑ChocolateFactoryBase或ConcreteChocolateFactory,但也许还有其他东西(就像Enums常常在Enum后缀,例如PetTypeEnum
以便您可以执行PetTypeEnum PetType;
希望这不是主观的。
最佳答案
问题与答案
好的,这个问题从抽象工厂的命名问题开始。根据经验,请始终使用您正在做的“正式”名称(例如Factory,Decorator等)和具体实现的描述(例如Snickers,Mars,MotifWidget等)。
因此,基本上,您创建的MSSQLConnection
是您要描述的具体内容,而Factory
则意味着它遵循了工厂模式的特征。
好的,到目前为止,是命名和原始问题。现在为酷的东西。讨论是在C#中实现抽象工厂的最佳方法,这是一个不同的主题。我在用C#实现所有设计模式方面做了很多工作,在这里我将分享有关工厂的一些详细信息。开始:
抽象工厂和工厂
抽象工厂基本上是基类或接口与具体实现的组合。如果共享大量代码,则需要基类;否则,则需要接口。
我通常区分“工厂”和“抽象工厂”。工厂是创建(某种类型的)对象的事物,“抽象工厂”是创建任意类型的对象的事物。这样,可以得出结论,抽象工厂的实现就是工厂。这与下一条信息有关。
工厂模式
支持RTTI的语言能够实现工厂模式。工厂模式是创建对象的事物。最简单的实现是仅包含创建对象的方法的类,例如:
// ...
public void CreateConnection()
{
return new SqlConnection();
}
// ...
public T Create(string name)
{
// lookup constructor, invoke.
}
Type
。查找名称,使用反射创建对象。做完了
MotifFactory
和
PMFactory
。将来我们还会遇到另一个UI东西,我们需要一个
ASPNETFactory
或
SilverlightFactory
。但是,未来是未知的,如果我们不需要,则不要发布旧的DLL-毕竟这不灵活。
/// <summary>
/// This attribute is used to tag classes, enabling them to be constructed by a Factory class. See the <see cref="Factory{Key,Intf}"/>
/// class for details.
/// </summary>
/// <remarks>
/// <para>
/// It is okay to mark classes with multiple FactoryClass attributes, even when using different keys or different factories.
/// </para>
/// </remarks>
/// <seealso cref="Factory{Key,Intf}"/>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class FactoryClassAttribute : Attribute
{
/// <summary>
/// This marks a class as eligible for construction by the specified factory type.
/// </summary>
/// <example>
/// [FactoryClass("ScrollBar", typeof(MotifFactory))]
/// public class MotifScrollBar : IControl { }
/// </example>
/// <param name="key">The key used to construct the object</param>
/// <param name="factoryType">The type of the factory class</param>
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;
}
/// <summary>
/// The key used to construct the object when calling the <see cref="Factory{Key,Intf}.Create(Key)"/> method.
/// </summary>
public object Key { get; private set; }
/// <summary>
/// The type of the factory class
/// </summary>
public Type FactoryType { get; private set; }
}
/// <summary>
/// Provides an interface for creating related or dependent objects.
/// </summary>
/// <remarks>
/// <para>
/// This class is an implementation of the Factory pattern. Your factory class should inherit this Factory class and
/// you should use the [<see cref="FactoryClassAttribute"/>] 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 <typeparamref name="Intf"/> type and are stored by key. During runtime, you can
/// use the Factory class implementation to build objects of the correct type.
/// </para>
/// <para>
/// 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).
/// </para>
/// <para>
/// Implementation of the Strategy pattern can be done by using the Factory pattern and making the <typeparamref name="Intf"/>
/// 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.
/// </para>
/// </remarks>
/// <typeparam name="Key">The type of the key to use for looking up the correct object type</typeparam>
/// <typeparam name="Intf">The base interface that all classes created by the Factory share</typeparam>
/// <remarks>
/// The factory class automatically hooks to all loaded assemblies by the current AppDomain. All classes tagged with the FactoryClass
/// are automatically registered.
/// </remarks>
/// <example>
/// <code lang="c#">
/// // 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
/// </code>
/// </example>
public abstract class Factory<Key, Intf> : IFactory<Key, Intf>
where Intf : class
{
/// <summary>
/// Creates a factory by mapping the keys of the create method to the keys in the FactoryClass attributes.
/// </summary>
protected Factory() : this((a) => (a)) { }
/// <summary>
/// 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.
/// </summary>
/// <param name="typeConversion">A function that maps keys passed to <see cref="Create(Key)"/> to keys used with [<see cref="FactoryClassAttribute"/>]</param>
protected Factory(Func<Key, object> typeConversion)
{
this.typeConversion = typeConversion;
}
private Func<Key, object> typeConversion;
private static object lockObject = new object();
private static Dictionary<Type, Dictionary<object, Type>> dict = null;
/// <summary>
/// Creates an instance a class registered with the <see cref="FactoryClassAttribute"/> attribute by looking up the key.
/// </summary>
/// <param name="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.</param>
/// <returns>An instance of the factory class</returns>
public virtual Intf Create(Key key)
{
Dictionary<Type, Dictionary<object, Type>> dict = Init();
Dictionary<object, Type> factoryDict;
if (dict.TryGetValue(this.GetType(), out factoryDict))
{
Type t;
return (factoryDict.TryGetValue(typeConversion(key), out t)) ? (Intf)Activator.CreateInstance(t) : null;
}
return null;
}
/// <summary>
/// Creates an instance a class registered with the <see cref="FactoryClassAttribute"/> attribute by looking up the key.
/// </summary>
/// <param name="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.</param>
/// <param name="constructorParameters">Additional parameters that have to be passed to the constructor</param>
/// <returns>An instance of the factory class</returns>
public virtual Intf Create(Key key, params object[] constructorParameters)
{
Dictionary<Type, Dictionary<object, Type>> dict = Init();
Dictionary<object, Type> factoryDict;
if (dict.TryGetValue(this.GetType(), out factoryDict))
{
Type t;
return (factoryDict.TryGetValue(typeConversion(key), out t)) ? (Intf)Activator.CreateInstance(t, constructorParameters) : null;
}
return null;
}
/// <summary>
/// Enumerates all registered attribute keys. No transformation is done here.
/// </summary>
/// <returns>All keys currently known to this factory</returns>
public virtual IEnumerable<Key> EnumerateKeys()
{
Dictionary<Type, Dictionary<object, Type>> dict = Init();
Dictionary<object, Type> factoryDict;
if (dict.TryGetValue(this.GetType(), out factoryDict))
{
foreach (object key in factoryDict.Keys)
{
yield return (Key)key;
}
}
}
private void TryHook()
{
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(NewAssemblyLoaded);
}
private Dictionary<Type, Dictionary<object, Type>> Init()
{
Dictionary<Type, Dictionary<object, Type>> d = dict;
if (d == null)
{
lock (lockObject)
{
if (dict == null)
{
try
{
TryHook();
}
catch (Exception) { } // Not available in this security mode. You're probably using shared hosting
ScanTypes();
}
d = dict;
}
}
return d;
}
private void ScanTypes()
{
Dictionary<Type, Dictionary<object, Type>> classDict = new Dictionary<Type, Dictionary<object, Type>>();
foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies())
{
AddAssemblyTypes(classDict, ass);
}
dict = classDict;
}
private void AddAssemblyTypes(Dictionary<Type, Dictionary<object, Type>> classDict, Assembly ass)
{
try
{
foreach (Type t in ass.GetTypes())
{
if (t.IsClass && !t.IsAbstract &&
typeof(Intf).IsAssignableFrom(t))
{
object[] fca = t.GetCustomAttributes(typeof(FactoryClassAttribute), false);
foreach (FactoryClassAttribute f in fca)
{
if (!(f.Key is Key))
{
throw new InvalidCastException(string.Format("Cannot cast key of factory object {0} to {1}", t.FullName, typeof(Key).FullName));
}
Dictionary<object, Type> keyDict;
if (!classDict.TryGetValue(f.FactoryType, out keyDict))
{
keyDict = new Dictionary<object, Type>();
classDict.Add(f.FactoryType, keyDict);
}
keyDict.Add(f.Key, t);
}
}
}
}
catch (ReflectionTypeLoadException) { } // An assembly we cannot process. That also means we cannot use it.
}
private void NewAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
{
lock (lockObject)
{
// Make sure new 'create' invokes wait till we're done updating the factory
Dictionary<Type, Dictionary<object, Type>> classDict = new Dictionary<Type, Dictionary<object, Type>>(dict);
dict = null;
Thread.MemoryBarrier();
AddAssemblyTypes(classDict, args.LoadedAssembly);
dict = classDict;
}
}
}
关于c# - GoF Factory的命名约定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31263041/
既然 GOF 的书是在 .Net 出现之前就整理好的,那么 GOF 中描述的特定模式是否不适合 .Net?如果是,原因是什么? 这是一个与最近赏金相关的问题 discussion . 最佳答案 GoF
此模式使用抽象工厂,然后使用工厂的实现。 我确定这两个类有一个标准的命名约定,但我不知道它是什么。 例如: public abstract class ChocolateFactory { }; pu
从 java 数据集中计算拟合优度 (GOF) 的选项是什么,我正在查看 apache math 3.0 库,但我无法理解使用它计算 GOF 的方法。对其他库或 math 3.0 有什么建议吗? 最佳
此主题的 Stackover 流相关帖子: Post_1和 Post_2 上面的帖子很好,但我仍然无法回答我的困惑,因此我把它作为一个新帖子放在这里。 我的问题 基于 GOF 的 Elements o
是否有任何 C# GOF 设计模式示例?我一直在寻找 this site确实有示例,但“C# 优化”示例仅在您购买其中一种产品时可用。 最佳答案 Steven John Metsker 写的一本名为“
我应该用 Java 创建一个迷你命令解释器 (System.in),以支持使用适当的 GoF 模式对图形对象进行操作。解释器的语法是一种简单的 EBNF 语言,如下所示:` ::=|||||||| :
让我们面对现实吧。单例模式是 highly controversial围墙两边都有大批程序员的话题。有些人觉得 Singleton 只不过是一个美化的全局变量,而另一些人则坚信模式并不断使用它。我不想
自从我开始学习 F#和 OCaml去年,我阅读了大量文章,这些文章坚持认为设计模式(尤其是在 Java 中)是命令式语言中缺失功能的解决方法。我找到的一篇文章 makes a fairly stron
我已阅读 wikipedia 装饰器模式用于.Net和Java IO类。 有人能解释一下这是如何使用的吗?举个可能的例子,它有什么好处? 维基百科上有一个 Windows 表单 示例,但我想知道 Ja
我们目前正在将 Access 应用程序大规模转换为 .NET 前端。许多 Access Apps 都有报表和创建 RDLC(或 Crystal rpt)的方法,并且带有数据集填充和绑定(bind)的主
我们需要构建一个解决方案来处理销售订单。处理是连续进行的:每个步骤负责特定的任务:检查客户是否有信用,检查所需元素是否有库存等。 我们想到使用 chain of responsibility patt
四人帮 Design Patterns使用文字处理器作为至少一些模式的示例,尤其是 Composite 和 Flyweight。 除了使用 C 或 C++ 之外,您真的可以使用这些模式和它们带来的面向
我正在模拟一种情况,其中有: NotificationBox:观察者 list1, list2, list3:主题 现在我会制作一张图表,其中使用观察者模式描述每个列表实现不同类型的 notify()
我正在讨论一些设计模式问题,并查看了 GoF 中装饰器模式的定义和示例。它说 Attach additional responsibilities to an object dynamically.
我很想知道哪个 GoF 设计模式直接转化为特定的 SOLID 原则?例如,我认为(在我看来)策略模式转化为依赖倒置原则。 不幸的是,我找不到任何研究他们关系的文献。如果能够更有效地学习彼此的观点,那就
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 3年前关闭。 Improve this questi
如果将来您只能使用 Gang of Four book 中定义的一个规范模式。 ,您会选择哪一个?出于什么原因? 最佳答案 不是一种设计模式,但对我来说,这个原则绝对是对我整本书的编程风格影响最大的:
这个问题的答案是community effort .编辑现有答案以改进这篇文章。它目前不接受新的答案或互动。 我正在学习 GoF Java 设计模式,我想看看它们的一些真实例子。 Java 核心库中这
我正在使用kendoTreeList 我正在尝试扩展所有组。这是我的code sample 但似乎 kendoTreeList 仅支持扩展第一组。我也在扩展方法中尝试了以下选择器。 treeList.
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Which are C# native built-in design patterns? Design P
我是一名优秀的程序员,十分优秀!