复合模式作为生产系统的模型

时间:2014-02-23 10:39:04

标签: c# design-patterns composite

我正在尝试使用复合模式对生产系统进行建模。简而言之,生产系统包含设施=>工厂=> subsystems =>工作站=> activities => subactivities =>元素。但是我觉得我没有把它做得很对,所以我真的很感激一些帮助!

首先,我得到这个奇怪的错误,说“Activity不包含一个带有0个参数的构造函数”用于“Workstation”类,而谷歌没有给我任何有用的问题(在我至少没有什么可以申请的。)

其次我只是想知道我是否有正确的想法?我见过的所有例子都包含Interface作为父类,我应该实现的是什么?说到这些例子,如果有人有一个类似我的例子的指南(而不仅仅是常规Boss =>经理= =员工示例,只有三步)我真的很感激!

这是我到目前为止制作的代码:

class Element
{
    public int basicActivityIdx;   //GET - S[101], GS80 [102] etc PUT - AW[201], S[202], PD80[203] etc.. 

    public Element(int idx)
    {
        this.basicActivityIdx = idx;   //GET - S[101], GS80 [102] etc PUT - AW[201], S[202], PD80[203] etc.. 
    }

}

 class SubActivity : Element
{
    private string subActivityName;

    public void SubActivity(string name)
    {
        this.subActivityName = name;
    }


    private List<Element> childElements = new List<Element>();
    public void addChildElement(Element inElement)
    {
        childElements.Add(inElement);
    }

}

class Activity : SubActivity
{
    public string activityName;
    public int activityFrequency; // Index to the list of choises ([1]every cycle, [2]every batch, [3]periodically)

    public void Activity(string name, int idx)
    {
        this.activityName = name;
        this.activityFrequency = idx;
    }

    private List<SubActivity> childSubActivities = new List<SubActivity>();
    public void addSubActivity(SubActivity inSubActivity)
    {
        childSubActivities.Add(inSubActivity);
    }

}

class Workstation : Activity
{
    private string workstationName;
    public void Workstation(string name)
    {
        workstationName = name;
    }


    private List<Activity> childActivities = new List<Activity>();
    public void addActivity(Activity inSubActivity)
    {
        childActivities.Add(inSubActivity);
    }
}

class SubSystem : Workstation
{
    public string subSystemName;

    public void SubSystem(string name)
    {
        this.subSystemName = name;
    }

    private List<Workstation> childWorkstations = new List<Workstation>();
    public void addWorkstation(Workstation inWorkstation)
    {
        childWorkstations.Add(inWorkstation);
    }
}

class Factory : SubSystem
{
    public string factoryName;
    public void Factory(string name)
    {
        this.factoryName = name;
    }

    private List<SubSystem> childSubSystems = new List<SubSystem>();
    public void addSubSystem(SubSystem inSubSystem)
    {
        childSubSystems.Add(inSubSystem);
    }
}

class Facility : Factory
{
    public string facilityName;

    public void Facility(string name) 
    {
        this.facilityName = name;
    }

    private List<Element> childFactories = new List<Element>();
    public void addFactory(Factory inFactory)
    {
        childFactories.Add(inFactory);
    }

}

2 个答案:

答案 0 :(得分:3)

首先,关于设计模式本身。您实施的复合与GOF Composite不同。你已经做了某种变体形式。 (我认为这不是你所期望的。)

第二,顶级类型Element(GOF - &gt;组件)不能是接口类型,但它应该是,因为推导应该(通常)提出他们自己的实施。至少顶级类型应该是抽象的。通过使用此方法,子类不需要维护顶级或ist父类型的引用列表。


只是一个伪源示例:

abstract class Element
{
    protected int basicActivityIdx;   //GET - S[101], GS80 [102] etc PUT - AW[201], S[202], PD80[203] etc.. 
    protected string basicActivityName;

    protected Element(int idx, string name)
    {
        this.basicActivityIdx = idx;   //GET - S[101], GS80 [102] etc PUT - AW[201], S[202], PD80[203] etc.. 
        this.basicActivityName = name;
    }

    public abstract void addChild(Element child);
    public abstract void doSthOperation();
    // TODO -> Define further operations ...
}

// Maybe you won't need this. It just tells you that the current node doesn't have any children
class Leaf : Element{
    public void Leaf(int idx, string name) : base(idx, name){}

    public void addChild(Element child){
        throw new SystemException("A leaf isn't allowed to have children!");
    }

    public void doSthOperation(){
        Console.WriteLine("I am the last node in the hierarchy!");
    }
}

class Activity : Element
{
    private List<Element> children;
    public void Activity(int idx, string name) : base(idx, name)
    {
        this.children = new List<Element>();
    }

    public void addChild(Element child){
        this.children.add(child);
    }

    public void doSthOperation(){
        Console.WriteLine("I am a concreate instance of Activity!");
    }
}

class SubActivity : Activiy{
    // This implementation doesn't have to maintain a list of top level elements, since its base class already is doing this!
    public void SubActivity(int idx, string name) : base(idx, name) { }

    public void addChild(Element child){
        base.addChild(child); 
        // Or implement its own behavior how children are added to the list.
        // Maybe you want to add any specific data to the the attached child here.
    }

    public void doSthOperation(){
        Console.WriteLine("I am a concreate instance of SubActivity!");
    }
}

可以满足您的需求的另一个示例,因为SubSystem不能是FactoryFactory不能是Facility }

// With this approach the element can never be a pure abstract class (interface)!
// The benefit of this version, in contrast to the previous one, is that the design
// of the software can be easily adapted to the real worlds structure, since it is defined
// dynamically, instead of staticaly like in the example above.
abstract class Element
{
    protected int id;   //GET - S[101], GS80 [102] etc PUT - AW[201], S[202], PD80[203] etc.. 
    protected string name;
    // This instance itself maintains a list of self references
    protected List<Element> children;

    protected Element(int id, string name)
    {
        this.children = new List<Element>();
        this.id = idx;   //GET - S[101], GS80 [102] etc PUT - AW[201], S[202], PD80[203] etc.. 
        this.name = name;
    }

    public void addChild(Element child){
        this.children.add(child);
    }

    public virtual void doSthOperation(){
        Console.WriteLine("I am the element instance itself!");
    }
    // TODO -> Define further operations ...
}

// Maybe you won't need this. It just tells you that the current node doesn't have any children
class Leaf : Element{
    public void Leaf(int id, string name) : base(id, name){}

    public void addChild(Element child){
        throw new SystemException("A leaf isn't allowed to have children!");
    }

    public void doSthOperation(){
        Console.WriteLine("I am the last node in the hierarchy!");
    }
}

class Facility : Element
{
    public void Facility(int id, string name) : base(id, name)

    public void doSthOperation(){
        Console.WriteLine("I am a concreate instance of Faciltiy!");
    }
}

class Factory : Element{
    public void Factory(int id, string name) : base(id, name) { }

    public void doSthOperation(){
        Console.WriteLine("I am a concreate instance of Factory!");
    }
}

class SubSystem : Element{
    public void SubSystem(int id, string name) : base(id, name) { }

    public void doSthOperation(){
        Console.WriteLine("I am a concreate instance of SubSystem!");
    }
}

答案 1 :(得分:2)

当您继承Workstation中的Activity并且Activity没有默认构造函数采用零参数时,您必须使用其中一个可用的contstructors,Activity(字符串名称,int idx),或者添加一个parmeterless构造函数。

public void Workstation(string name) : base(name, -1)
{
    workstationName = name;
}

如果base是您继承的类,则需要将theese属性转发给基类以便实例化它。 -1是idx参数,名称是

似乎所有类都继承自Element我建议您在构造函数中向所有子类添加ID参数,并将Name属性添加到Element类。那么你就不必宣布一个新的名字&#34;所有子类的属性。

class Element
{
    protected int _idx;  
    protected string _name; 

    public int Idx { get { return _idx; } }
    public string Name { get { return _name; } }


    public Element(int idx, string name)
    {
      _idx = idx;   
      _name = name;
    }
}

然后向所有子类添加构造函数,并将参数转发给基类。

class SubActivity : Element {

   public SubActivity(int idx, string name) : base(idx, name)
   {
   }

 }

当你在c#中定义一个类并且没有明确地创建一个构造函数时,编译器会为你做这个。但是一旦你定义了一个构造函数,那么你将只有那个构造函数。

没有构造函数接受零参数的类(默认构造函数)必须使用所需参数进行实例化,因此使用子类中的base关键字将所需参数传递给基类。

伪示例:

class Foo{}

// Foo be instanciated by the "automatic" default constructor

new Foo()

class Boo{
   Boo(string name){}
}

// Boo cannot be instanciated without the required parameter: name

Boo() 
// will give you an compilation error: Boo does not contain a constructor taking zero arguments

Boo("the boo") // will work finem thus the parameter: name, is supplied

// the same goes for inheritance

class Moo : Boo {}
// in order to instanciate Moo which IS Boo by inheritance you need to get the required arguments passed from Moo to Boo

这可以通过修改Boo手动添加默认构造函数或在子类Moo中添加构造函数来解决,该构造函数采用&#39; name&#39;参数并使用base关键字将其传递给基类(Boo)。哪一个最适合你的设计。

Alt 1.(修改基类)

class Boo{
  Boo(){ ... _name = "default name"; ... } // define default constructor
  Boo(string name){}
}

Alt 2.(修改子类)

class Moo : Boo {
  Moo(string name) : base(name){}
}