如何告诉一个类应该创建哪些对象?类型与对象混淆:(

时间:2018-11-03 09:00:31

标签: c# methods types

我有一个想要处理规则(以某种方式)的类(SetOfRules)。 任务:创建此类的新实例(这很简单),然后向该实例添加规则(在Rules和派生类中定义)。

问题1:我不想实例化所有规则,然后将它们作为对象传递给SetOfRules的添加方法,但我想将类名称(类型)的列表传递给添加方法。我怎么做? 然后在SetOfRules内部实例化此类对象的语法如何?

问题2:类规则和派生类不包含任何属性。它们只是转换方法的集合。 我是否必须将它们实例化为SetOfRules类中的对象,还是可以将它们称为静态类的方法(我不能使用静态类,因为我在Rule类上使用继承来确保每个规则类都实现了以下方法:需要)

这是我现在遇到的一些(伪)代码:

public class Rule
{
    virtual void transform( myObject ob)
    {
        ...
    }
}

public class SpecificRule1 : Rule
{
    ...
}

public class SpecificRule2 : Rule
{
    ...
}



public class SetOfRules
{
    public AddRules( ???? ListOfRuleTypes)
    {
    }
}

我想在其他地方做类似的事情

SetOfRules easyRules = new SetOfRules();
easyRules.Add( new ??RuleTypes??[] { "SpecificRule2", "SpecificRule13", "SpecificRule22" });

感谢您的酷提示!

3 个答案:

答案 0 :(得分:2)

您似乎想要一个带有合同的单身人士课程:

public interface IRule
{
    void Transform(object o);
}
public abstract class SingletonBase<T> where T : SingletonBase<T>, new()
{
    public static T Instance { get; } = new T();
}
public class SpecificRule1 : SingletonBase<SpecificRule1>, IRule
{
    public void Transform(object o) => throw new NotImplementedException();
}
public class SpecificRule2 : SingletonBase<SpecificRule2>, IRule
{
    public void Transform(object o) => throw new NotImplementedException();
}
public class RuleSet : List<IRule>
{
    public void Add<TRule>() where TRule : SingletonBase<TRule>, IRule, new()
    {
        this.Add(SingletonBase<TRule>.Instance);
    }
}

您可以通过各种方式添加规则:

var rules = new RuleSet
{
    SpecificRule1.Instance,
    SpecificRule2.Instance,
};

rules = new RuleSet();
rules.Add(SpecificRule1.Instance);
rules.Add<SpecificRule2>();

答案 1 :(得分:1)

示例-计算订单商品折扣的规则:

public static void WriteFile(String strWrite) {
        String strFileName = "Agilanbu.txt"; // file name
        File myFile = new File("sdcard/Agilanbu"); // file path 
        if (!myFile.exists()) { // directory is exist or not
            myFile.mkdirs();    // if not create new
            Log.e("DataStoreSD 0 ", myFile.toString());
        } else {
            myFile = new File("sdcard/Agilanbu");
            Log.e("DataStoreSD 1 ", myFile.toString());
        }

        try {
            File Notefile = new File(myFile, strFileName); 
            FileWriter writer = new FileWriter(Notefile); // set file path & name to write
            writer.append("\n" + strWrite + "\n"); // write string
            writer.flush();
            writer.close();
            Log.e("DataStoreSD 2 ", myFile.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String readfile(File myFile, String strFileName) {
        String line = null;
        try {
            FileInputStream fileInputStream = new FileInputStream(new File(myFile + "/" + strFileName)); // set file path & name to read
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); // create input steam reader 
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuilder stringBuilder = new StringBuilder();
            while ((line = bufferedReader.readLine()) != null) { // read line by line
                stringBuilder.append(line + System.getProperty("line.separator")); // append the readed text line by line
            }
            fileInputStream.close();
            line = stringBuilder.toString(); // finially the whole date into an single string
            bufferedReader.close();
            Log.e("DataStoreSD 3.1 ", line);
        } catch (FileNotFoundException ex) {
            Log.e("DataStoreSD 3.2 ", ex.getMessage());
        } catch (IOException ex) {
            Log.e("DataStoreSD 3.3 ", ex.getMessage());
        }
        return line;
    }

use this code to write ---  WriteFile(json); // json is a string type
use this code to read  ---  File myFile = new File("sdcard/Agilanbu");
                            String strObj = readfile(myFile, "Agilanbu.txt");

// you can put it in seperate class and just call it where ever you need.(for that only its in static)
// happie coding :)

折扣合同(又名接口)可以这样定义:

public class OrderItem
{
    public int ItemId { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }

    public decimal Total => Quantity * Price;
}

现在让我们实施一些折扣规则

  • 基本折扣(2%)
  • 银牌折扣(5%)
  • 黄金折扣(10%)

类定义:

public interface IDiscountRule
{
    decimal CalculateDiscount(OrderItem item);
}

使用规则计算订单商品的折扣:

/// <summary>
/// Abstract base class for the discount rules
/// </summary>
public abstract class DiscountRule : IDiscountRule
{
    private readonly int _percent;

    protected DiscountRule(int percent)
    {
        _percent = percent;
    }

    /// <inheritdoc />
    public decimal CalculateDiscount(OrderItem item)
    {
        if (item == null)
        {
            throw new ArgumentNullException(nameof(item));
        }

        decimal discount = item.Total * (decimal) (_percent/100.0);

        return discount;
    }
}


/// <summary>
/// 2% discount
/// </summary>
public class BasicDiscountRule : DiscountRule
{
    public BasicDiscountRule() : base(2)
    {

    }
}

/// <summary>
/// 5% discount
/// </summary>
public class SilverDiscountRule : DiscountRule
{
    public SilverDiscountRule() : base(5)
    {

    }
}

/// <summary>
/// 10% discount
/// </summary>
public class GoldDiscountRule : DiscountRule
{
    public GoldDiscountRule() : base(10)
    {

    }
}

现在,我们创建一个合成规则,以便将多个规则(折扣)应用于订单商品:

var item = new OrderItem
{
    ItemId = 1,
    Price = 50,
    Quantity = 2
};

var rule = new SilverDiscountRule();
decimal discount = rule.CalculateDiscount(item);

您可以将复合规则与类型列表一起使用:

/// <summary>
/// To apply multiple discount rules to an order item
/// </summary>
public class CompositeDiscountRule : IDiscountRule
{
    private readonly List<Type> _discountTypes;

    public CompositeDiscountRule()
    {
        _discountTypes = new List<Type>();
    }

    public CompositeDiscountRule(List<Type> discountTypes)
    {
        if (discountTypes == null)
        {
            throw new ArgumentNullException(nameof(discountTypes));
        }

        _discountTypes = discountTypes;
    }

    public void Register<T>() where T : IDiscountRule, new()
    {
        _discountTypes.Add(typeof(T));
    }

    /// <inheritdoc />
    public decimal CalculateDiscount(OrderItem item)
    {
        decimal totalDiscount = 0;

        foreach (var discountType in _discountTypes)
        {
            IDiscountRule rule = Activator.CreateInstance(discountType) as IDiscountRule;

            if (rule != null)
            {
                totalDiscount += rule.CalculateDiscount(item);
            }
        }

        return totalDiscount;
    }
}

或者,或者使用泛型:

var item = new OrderItem
{
    ItemId = 1,
    Price = 50,
    Quantity = 2
};

// composite rule with types
var compositeRule = new CompositeDiscountRule(new List<Type>
{
    typeof(GoldDiscountRule),
    typeof(BasicDiscountRule)
});

decimal discount = compositeRule.CalculateDiscount(item); // discount = 12.0

答案 2 :(得分:0)

请阅读有关图案装饰器的信息。通过结构设计模式,您可以将新行为附加到包含这些行为的包装对象中,从而将新行为附加到对象。

我认为这将帮助您解决第一个问题

有用的链接:https://refactoring.guru/design-patterns/decorator