I'm trying to model a production system using a composite pattern. In short, the production system contains of facilities => factories => subsystems => workstations => activities => subactivities => elements. But I don't think I'd got it quite right, so I'd really appreciate some help!
First of all, I'm getting this strange errors saying "Activity doesn't contain a constructor that takes 0 arguments" for the "Workstation" class, and google that didn't give me anything useful to my problem (at least nothing I could apply).
Secondly I'm kind of just wondering if I have thought right at all? All the examples I've seen contains Interface as the parent class, is that something I should implement as well? Speaking of the examples, if anyone have a guide with an example similar to mine (and not just the regular Boss => Manager => Employee example with just three steps) I'd really appreciate it!
Here's the code I've produced so far:
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);
}
}
First, concerning to the design pattern itself. The composite you have implemented isn't the same as the GOF Composite. You have made some kind a variant form of that. (I think this isn't what you expect.)
Second, the top level type Element
(GOF -> Component) must not be an interface type, but it should be, since the derivations should (normally) come up with their own implementation. At least the top level type should be abstract. By using this approach, the sub classes don't need to maintain a list of references to the top level or ist parent type.
Just a pseudo source example:
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!");
}
}
A further example which may suite your needs more, since a SubSystem
must not be a Factory
and a Factory
must not be a 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!");
}
}