我正在尝试使用复合模式对生产系统进行建模。简而言之,生产系统包含设施=>工厂=> 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);
}
}
答案 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
不能是Factory
而Factory
不能是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){}
}