在设计模式中可替代枚举
本文关键字:枚举 设计模式 | 更新日期: 2023-09-27 18:01:36
考虑一个基本组件base
具有像
enum
类型的情况public enum ItemState = { red, green, blue };
我在Project_1
, Project_2
等其他组件中使用此基础组件。
它们每个都做一些特定的事情,并且需要特定于项目的状态,例如Project_1
中的{grey, black, white, ...}
和Project_2
中的{brown, transparent, ...}
。
Project_1
不允许使用(如果可能的话甚至不允许看到){brown, transparent, ...}
。同理,Project_2
不能使用{grey, black, white, ...}
。
我知道"局部枚举"不存在——那么对于这样的任务,建议的设计模式是什么?
由于枚举不能继承,一种解决方案可能是使用具有静态常量成员的类,如下所示:
public class ItemState
{
protected ItemState() { }
public static ItemState red { get; } = new ItemState();
public static ItemState green { get; } = new ItemState();
public static ItemState blue { get; } = new ItemState();
}
然后在你的Project_1
中你可以派生一个自己的类:
public class ItemState_1 : ItemState
{
public static ItemState grey { get; } = new ItemState_1();
public static ItemState black white { get; } = new ItemState_1();
}
和Project_2
public class ItemState_2 : ItemState
{
public static ItemState brown { get; } = new ItemState_2();
public static ItemState transparent white { get; } = new ItemState_2();
}
这可能不是最舒服的方式,但这是我目前能想到的最好的方式。
你可以这样使用它们:
ItemState project1State = ItemState_1.grey;
if (project1State == ItemState_1.grey)
// do something
这些都编译得很好,但不幸的是,这些值不能在switch/case
语句中使用。这可以通过适当的ToString()
实现来解决,字符串字面值可以在switch/case
中使用。但是,这当然会给这些类/属性定义添加更多的代码。
我有点晚了,但这里是Rene的回答的"buff"版本(现在使用隐式强制转换!):
public class ColorEnum
{
protected readonly string Name;
protected readonly Color Value;
public static readonly ColorEnum Red = new ColorEnum(Color.Red, "Red");
public static readonly ColorEnum Green = new ColorEnum(Color.Green, "Green");
public static readonly ColorEnum Blue = new ColorEnum(Color.Blue, "Blue");
protected ColorEnum(Color value, string name)
{
Name = name;
Value = value;
}
public override string ToString()
{
return Name;
}
public static implicit operator Color(ColorEnum @enum)
{
return @enum.Value;
}
public static implicit operator string(ColorEnum @enum)
{
return @enum.Name;
}
}
public class AnotherColorEnum : ColorEnum
{
public static readonly ColorEnum Grey = new AnotherColorEnum(Color.Gray, "Grey");
public static readonly ColorEnum Black = new AnotherColorEnum(Color.Black, "Black");
public static readonly ColorEnum White = new AnotherColorEnum(Color.White, "White");
protected AnotherColorEnum(Color value, string name) : base(value, name)
{
}
}
这样你就可以像这样使用你的"enum":
var color = ColorEnum.Red;
var anothercolor = Color.Red;
if (color == anothercolor)
{
//DoSomething
}
或者像这样:
var color = ColorEnum.Red;
var anothercolor = "Red";
if (color == anothercolor)
{
//DoSomething
}
根据您的用例,您可能希望使用主/子集模式。
例如,我有一个包含所有可能值的enum:
/// <summary>
/// Types of limits that can be applied to a table, view, or table-value function query.
/// </summary>
/// <remarks>Databases are expected to provide their own enumeration that represents a subset of these options.</remarks>
[Flags]
public enum LimitOptions
{
/// <summary>
/// No limits were applied.
/// </summary>
None = 0,
/// <summary>
/// Returns the indicated number of rows with optional offset
/// </summary>
Rows = 1,
/// <summary>
/// Returns the indicated percentage of rows. May be applied to TableSample
/// </summary>
Percentage = 2,
/// <summary>
/// Adds WithTies behavior to Rows or Percentage
/// </summary>
WithTies = 4,
/// <summary>
/// Returns the top N rows. When there is a tie for the Nth record, this will cause it to be returned.
/// </summary>
RowsWithTies = Rows | WithTies,
/// <summary>
/// Returns the top N rpercentage of ows. When there is a tie for the Nth record, this will cause it to be returned.
/// </summary>
PercentageWithTies = Percentage | WithTies,
然后每个项目有它自己的值子集:
/// <summary>
/// Limit options supported by Access.
/// </summary>
/// <remarks>This is a strict subset of LimitOptions</remarks>
public enum AccessLimitOption
{
/// <summary>
/// No limits were applied.
/// </summary>
None = LimitOptions.None,
/// <summary>
/// Uses TOP
/// </summary>
RowsWithTies = LimitOptions.RowsWithTies,
}
子项目总是使用严格的子集,而不是使枚举可扩展。这允许我保持核心相当通用,同时在适当的地方提供特定于数据库的api。