简体   繁体   English

哪种设计模式可以获取此架构

[英]Which design pattern allows to get this architecture

I have the following objects : 我有以下对象:

  • Formula
  • Stock 股票
  • Counter 计数器
  • etc ... 等...

all these objects are called indicators and have common properties (Id, Name, Value...). 所有这些对象都称为指标,并且具有共同的属性(Id,Name,Value ...)。 Each entity has its own properties: 每个实体都有自己的属性:

  • Formula: FormulaExpression, FormulaCode, OperandsList ... 公式:FormulaExpression,FormulaCode,OperandsList ...
  • Stock: StockValue, StockLimit... 库存:StockValue,StockLimit ...
  • Counter: CounterIndex... 计数器:CounterIndex ...
  • etc ... 等...

So logically, i have to make indicator class containing the common properties, and for each entity i have to create a class that inherits from indicator. 因此,从逻辑上讲,我必须使包含通用属性的指标类成为现实,并且必须为每个实体创建一个从指标继承的类。

Formula is a special indicator that can contain any type of indicators. 公式是一种特殊的指标,可以包含任何类型的指标。 The formula's indicators are named operands. 公式的指标称为操作数。

the operand object has the following properties: operandId, operandCode, operandIndex 操作对象具有以下属性:操作对象编号,操作对象编号,操作对象编号

when i want to list the formula operands, i want to get objects which inherit from indicator, operand and entity type (create an object that have indicators properties, operand properties and stock properties for example) 当我想列出公式操作数时,我想获取从指标,操作数和实体类型继承的对象(例如,创建一个具有指标属性,操作数属性和股票属性的对象)

which design pattern or which architecture allows me to have this behaviour? 哪种设计模式或哪种体系结构可以使我具有这种行为?


To explain more the problem 解释更多问题

The entities ( Formula , stock , Counter ..) are Indicators and not necessary Operands , Operands are Indicators too. 实体( FormulastockCounter ..)是Indicators ,不是必需的OperandsOperands也是Indicators Object Indicator is the primitive type of entities, we can create an Indicator and then decorate it to become a Formula for example and than decorate it to become an Operand when it is added to another Formula . 对象Indicator是实体的原始类型,我们可以创建一个Indicator ,然后将其修饰为一个Formula ,例如,当将其添加到另一个Formula时,将其修饰为Operand

What I posted here may looks like a lot of code but it's actually very straightforward. 我在这里发布的内容可能看起来像很多代码,但实际上非常简单。

Most of the properties and constructors are there to simplify the script in the main function. 大多数属性和构造函数都可以简化主函数中的脚本。

The base concept is to create a Generic Class for the operands that contains a reference to the base Indicator object it's created from. 基本概念是为操作数创建一个通用类该类包含对创建它的基础Indicator对象的引用。

Test this code in an empty project and it'll be very easy to understand from the output. 在一个空项目中测试此代码,从输出中将很容易理解它。

class Indicator{
    // Common properties
}
class Counter : Indicator{
    public int CounterIndex;
    public Counter(int cI){
        CounterIndex = cI;
    }
    public void Print()
    {
        Console.WriteLine("CounterIndex: {0}", CounterIndex);
    }
}
class Operand{
    // Common operand properties
}
class Operand<T> : Operand{
    public T BaseIndicator;
    public Operand(T bI){
        BaseIndicator = bI;
    }
}
class Formula : Indicator{
    public string FormulaExpression;
    public int FormulaCode;
    public List<Operand> OperandsList = new List<Operand>();

    public Formula(string fE, int fC){
        FormulaExpression = fE;
        FormulaCode = fC;
    }

    public void Print ()
    {
        Console.WriteLine ("FormulaExpression: {0}; FormulaCode: {1}",
                           FormulaExpression, FormulaCode);
        if (OperandsList.Count == 0) {
            return;
        }
        Console.WriteLine("Begin Operands: ");
        foreach(Operand o in OperandsList){
            if(o is Operand<Counter>){
                Operand<Counter> cO = o as Operand<Counter>;
                cO.BaseIndicator.Print();
            }else if(o is Operand<Formula>){
                Operand<Formula> fO = o as Operand<Formula>;
                fO.BaseIndicator.Print();
            }else{
                // I'ts a simple Indicator
            }
        }
        Console.WriteLine("End Operands");
    }
}
class MainClass
{
    public static void Main (string[] args)
    {
        Counter c1 = new Counter(2);
        Counter c2 = new Counter(3);
        Formula f1 = new Formula("a + b", 7);
        Formula f2 = new Formula("a * b", 10);

        Formula f = new Formula("a ^ b", 32);
        f.OperandsList.Add(new Operand<Counter>(c1));
        f.OperandsList.Add(new Operand<Formula>(f1));
        f.OperandsList.Add(new Operand<Counter>(c2));
        f.OperandsList.Add(new Operand<Formula>(f2));
        f.Print();
        Console.ReadLine();
    }
}

The best way to do it would be to use an expando object that is filled by each operand using polymorphic dispatch . 最好的方法是使用由每个操作数使用多态调度填充的expando对象。 The expando object lets you add custom properties, and the polymorphic dispatch lets you close your code against operands change. expando对象使您可以添加自定义属性,而多态分派使您可以针对操作数更改关闭代码。

You would start by using a base class for the Operand that contains your basic elements 您将从使用包含基本元素的操作数的基类开始

public abstract class Operand
{
    public int Id { get; set; }
    public string Name { get; set; }

    public dynamic BuildObject()
    {
        dynamic o = new ExpandoObject();
        o.Id = Id;
        o.Name = Name;
        AddPropertiesToObject(o);
        return o;
    }

    protected internal abstract void AddPropertiesToObject(dynamic o);
}

Then adding a new Operand type is very easy since you can control what you will add to it independently: 然后添加新的Operand类型非常容易,因为您可以独立控制要添加的类型:

public class Stock : Operand
{
    public double StockValue { get; set; }

    protected internal override void AddPropertiesToObject(dynamic o)
    {
        // I decided to ignore the base class Id and Name
        // adding them would be trivial, but may not be what you need since 
        // it would overwrite the base values...
        // To add them you would have to wrap this virtual method call with
        // a call to a function doing the insertion in the base class 
        o.StockValue = StockValue;
    }
}

The Formula object would simply iterate on the contained operands and call their AddPropertiesToObject in turn (of course it can also add its own data but for the example I didn't include any) Formula对象将简单地对所包含的操作数进行迭代,然后依次调用其AddPropertiesToObject (当然,它也可以添加自己的数据,但是对于示例,我没有包含任何数据)

public class Formula : Operand
{
    public List<Operand> InnerOperands { get; set; }

    protected internal override void AddPropertiesToObject(dynamic o)
    {
        foreach (var op in InnerOperands)
        {
            op.AddPropertiesToObject(o);
        }
    }
}

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

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