简体   繁体   English

抽象工厂模式默认类问题

[英]Abstract Factory Pattern Default Class Issue

Hi, I've a class which has a method with some condition checks and append a string according to condition. 嗨,我有一个类,该类的方法带有一些条件检查并根据条件附加字符串。 I tried to refactor this code with abstract factory pattern. 我试图用抽象工厂模式重构此代码。

My problem is related to default expression class. 我的问题与默认表达式类有关。 If none of other rules applies to related filter, then I want to apply default expression rule. 如果没有其他规则适用于相关过滤器,那么我想应用默认表达式规则。 However on my application; 但是在我的申请中; it depends the order of StandartExpression instance order in the _expressions list. 它取决于_expressions列表中StandartExpression实例顺序的顺序。 If it is added first then the other rules will not be checked. 如果先添加,则不会检查其他规则。

I think I missed something about that pattern. 我想我错过了有关该模式的一些信息。 Could you help me? 你可以帮帮我吗?

This is my application code : 这是我的应用程序代码

public class Filter
{
    private string _operator = "="; // =, !=, <,> ...

    public string Name { get; set; }
    public object Value { get; set; }
    public string Operator { get { return _operator; } set { _operator = value; } }

}

Filter filter = null;
StringBuilder whereClause = new StringBuilder();

for (int i = 0; i < array.Length; i++)
{
    filter = array[i];

    if (filter.Value.ToString().ToLower().Equals("null"))
    {
        whereClause.Append(filter.Name + " " + filter.Operator + " null ");
    }
    else if (filter.Operator.ToLower().Equals("like"))
    {
        whereClause.Append(filter.Name + ".Contains(@" + i + ")");
    }
    else
    {
        whereClause.Append(filter.Name + " " + filter.Operator + " @" + i);
    }
    whereClause.Append(" AND ");
}

Now, this is the abstract factory pattern code: 现在,这是抽象的工厂模式代码:

public interface ICustomExpression
{
    bool ExpressionIsValid(Filter filter);
    string GetExpressionStr(Filter filter, int index);
}


public class StandardExpression : ICustomExpression
{
    public bool ExpressionIsValid(Filter filter)
    {
        return true;
    }

    public string GetExpressionStr(Filter filter, int index)
    {
        return filter.Name + " " + filter.Operator + " @" + index;
    }
}

public class LikeExpression : ICustomExpression
{
    public bool ExpressionIsValid(Filter filter)
    {
        return filter.Operator.ToLower().Equals("like");
    }

    public string GetExpressionStr(Filter filter, int index)
    {
        return filter.Name + ".Contains(@" + index + ")";
    }
}
public class NullExpression : ICustomExpression
{
    public bool ExpressionIsValid(Filter filter)
    {
        return filter.Value.ToString().ToLower().Equals("null");
    }

    public string GetExpressionStr(Filter filter, int index)
    {
        return filter.Name + " " + filter.Operator + " null ";
    }
}

public static class ExpressionFactory
{
    private static List<ICustomExpression> _expressions = null;
    public static List<ICustomExpression> Expressions
    {
        get
        {
            if (_expressions == null)
            {
                Build();
            }
            return _expressions;
        }
    }

    private static void Build()
    {
        _expressions = new List<ICustomExpression>();
        _expressions.Add(new NullExpression());
        _expressions.Add(new LikeExpression());
        _expressions.Add(new StandardExpression());
    }
}

And that is how I used that structure on my application code : 这就是我在应用程序代码中使用该结构的方式:

StringBuilder whereClause = new StringBuilder();
Filter filter = null;
var array = filterList.ToArray();
for (int i = 0; i < array.Length; i++)
{
    filter = array[i];

    foreach (ICustomExpression exp in ExpressionFactory.Expressions)
    {
        if (exp.ExpressionIsValid(filter))
            whereClause.Append(exp.GetExpressionStr(filter, i));
    }


    whereClause.Append(" AND ");
}

Your feeling is right: there is a hidden distinction between "special" and "standard" expressions that should be made explicit for clarity. 您的感觉是正确的:“特殊”和“标准”表达式之间存在隐藏的区别,为清楚起见,应明确表达它们。

However, in my eyes the bigger problem is that your factory is not actually handling the type selection and instantiation on its own but is delegating parts of that responsibility to its clients. 但是,在我看来,更大的问题是您的工厂实际上不是在自行处理类型选择和实例化,而是将部分责任委托给客户。 Every client has to know how to work with the collection property Expressions and thus also has to know about this implicit distinction I mentioned above. 每个客户端都必须知道如何使用集合属性Expressions ,因此还必须了解我上面提到的这种隐式区别。

Ideally clients of the ExpressionFactory should just hand it a filter in order to get the correct ICustomExpression instance. 理想情况下, ExpressionFactory客户端应该只将其交给过滤器,以获取正确的ICustomExpression实例。 Here's how this might look like: 这可能是这样的:

public static class ExpressionFactory
{
    private static StandardExpression _standardExpression = new StandardExpression();

    private static ICustomExpression[] _specialExpressions = new []
    {
        (ICustomExpression)new NullExpression(),
        (ICustomExpression)new LikeExpression()
    };

    public static ICustomExpression GetBy(Filter filter)
    {
        var match = _specialExpressions.SingleOrDefault(e => e.ExpressionIsValid(filter));

        if (match == null)
            return _standardExpression;

        return match;
    }
}

The rules how an expression is created (or rather selected, in your case) is now only known by the factory and thus implemented in a single place. 现在,仅由工厂知道如何创建(或在您的情况下选择)表达式的规则,因此可以在一个地方实现。

I also made the implicit distinction between "special" and "standard" expressions explicit, so the implementation does not depend on the order in which the ICustomExpression s are added anymore. 我还明确指出了“特殊”和“标准”表达式之间的隐式区别,因此实现不再依赖于ICustomExpression的添加顺序。

Note that the usage of the factory now becomes more straight-forward: 请注意,工厂的用法现在变得更加简单:

for (int i = 0; i < array.Length; i++)
{
    filter = array[i];  
    var exp = ExpressionFactory.GetBy(filter);          
    whereClause.Append(exp.GetExpressionStr(filter, i));        
    whereClause.Append(" AND ");
}

Here is a working example of the refactored code: https://dotnetfiddle.net/uzVJhM 这是重构代码的工作示例: https : //dotnetfiddle.net/uzVJhM

By the way: your implementation looks more like an instance of the factory method pattern . 顺便说一句:您的实现看起来更像是工厂方法模式的实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM