• Advertisement
Sign in to follow this  

Help with Prototype pattern ontop of composite pattern

This topic is 3003 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a set of classes all derived from one class "Modual" A Modual object contains a list of other Modual objects, AKA the composite pattern. Each of these Modual objects always of a type derived from Modual so as to provide different functionality. No I am trying to implement the prototype pattern to make copies of entire object structures. In fact I've been successful in this. The problem is that I want a some what cleaner solution. I have two functions, Clone and Copy. Copy is implement in the base class Modual and is responsible for recursively walking the composite structure and creating an duplicate structure. Clone is implemented in each derived class and simply returns a new object of the derived type. What I want is to not have to have two functions and to only implement Copy in the base class. The only trouble I'm having here is how to I make a new object of the derived type from with in the base class? I striped out a lot of extra code from this example because its really huge and most of it is unrelated to the question at hand.
namespace Mhz
{
    public abstract class Modual
    {
        protected static int stepsPerSecond = 44100;
        protected static double deltaT = 1.0 / stepsPerSecond;
        protected static double TwoPI = 2.0 * System.Math.PI;
        public System.Collections.Generic.List<Modual> Inputs;
        public double value;
        bool Processing, Copying;

        public Modual()
        {
            Inputs = new List<Modual>();
            Processing = false;
            Copying = false;
            value = 0.0;
        }

        protected abstract Modual Clone();
        public Modual Copy()
        {
            Modual T = null;
            if (!Copying)
            {
                Copying = true;
                T = Clone(); // <- This is implemented in each derived class and returns a new object of the derived type. See below definition.
                T.value = value;
                foreach (Modual M in Inputs)
                {
                    T.Inputs.Add(M.Copy());
                }
                Copying = false;
            }
            return T;
        }
       

        public void process()
        {
            if (!Processing)
            {
                Processing = true;
                foreach (Modual Mdl in Inputs)
                    Mdl.process();
                //if (In != null) In.process();
                //if (Mod != null) Mod.process();
                Processing = false;
            }
        }
        virtual public void ConectIn(ref Modual con)
        {
            Inputs.Add(con);
        }
        
    }

    
    public class Dial : Modual
    {
        override protected Modual Clone() { return (Modual)new Dial(); } // <- I want to avoid the need to have one of these in each derived class. 
        override public void process()
        {
        }
    }

    public abstract class SignalGen : Modual
    {
        protected double Theta = 0;
        protected double Hz = 100;

        override public void process()
        {
            base.process();
            Hz = Math.Abs(Inputs[Inputs.Count - 1].value);
            Theta += (deltaT * Hz * TwoPI);
            if (Theta >= TwoPI) Theta -= TwoPI;
        }
    };

    public class SinWave : SignalGen
    {
        override protected Modual Clone() { return (Modual)new SinWave(); }
        override public void process()
        {
            base.process();
            value = Math.Sin(Theta);
        }
    };

    public class SawWave : SignalGen
    {
        override protected Modual Clone() { return (Modual)new SawWave(); }
        override public void process()
        {
            base.process();
            value = -1.0 + (Theta / TwoPI * 2.0);
        }
    }

    public class ISawWave : SignalGen
    {
        override protected Modual Clone() { return (Modual)new ISawWave(); }
        override public void process()
        {
            base.process();
            value = 1.0 - (Theta / TwoPI * 2.0);
        }
    }

    public class TiangleWave : SignalGen
    {
        override protected Modual Clone() { return (Modual)new TiangleWave(); }
        override public void process()
        {
            base.process();
            if (Theta < System.Math.PI)
                value = -1.0 + (Theta / System.Math.PI * 2);
            else
                value = -1.0 + ((TwoPI - Theta) / System.Math.PI * 2);
        }
    }

    public class SquareWave : SignalGen
    {
        double DutyCycle;
        override protected Modual Clone() { return (Modual)new SquareWave(); }
        public override void process()
        {
            base.process();
            //if (In != null) DutyCycle = In.value; else DutyCycle = .5;
            if (Inputs.Count > 1) DutyCycle = Inputs[0].value; else DutyCycle = .5;
            if (Theta < DutyCycle * TwoPI) value = 1.0;
            else value = -1.0;
        }
    }
    
    class Adder : Modual
    {
        override protected Modual Clone() { return (Modual)new Adder(); }
        override public void process()
        {
            base.process();
            value = 0;
            foreach (Modual I in Inputs)
            {
                value += I.value;
            }
        }
    }
    class Inverter : Modual
    {
        override protected Modual Clone() { return (Modual)new Inverter(); }
        override public void process()
        {
            base.process();
            value = -Inputs[0].value;
        }
    }
public class DelayLine : Modual
    {
        System.Collections.Queue Doubles; //overide ConnectMod and set this guys size
        override protected Modual Clone() { return (Modual)new DelayLine(Doubles.Count); }
        public DelayLine(int Length)
        {
            Doubles = new System.Collections.Queue();
            for (int i = 0; i <= Length; i++)
            {
                Doubles.Enqueue((double)0.0);
            }
        }
        override public void process()
        {
            base.process();
            //Doubles.Count (int)Mod.value; Resize Queue (Streach or compress data)
            Doubles.Enqueue(Inputs[0].value);
            value = (double)Doubles.Dequeue();
        }
    }

}



Share this post


Link to post
Share on other sites
Advertisement
The word is spelled "Module".

Quote:
What I want is to not have to have two functions and to only implement Copy in the base class.


I don't think that's going to work, sorry.

Share this post


Link to post
Share on other sites
No matter what, you are going to need to be able to create an object of a particular derived type given an instance of that type. If you don't want to provide that functionality with a virtual method then you could have a static factory method in the base class that takes a derived type and creates an object of the same type, but in order to do this you would need to add a virtual method that returns a unique (say) enum for each derived type or use runtime type information. Not sure what it would buy you to do this, and the factory method would be ugly, basically a big switch statement.

Share this post


Link to post
Share on other sites
So is there no way to dynamically determine type at runtime and get different behavior....

Like instead of T = Clone(); using something T = (Modual)this.GetType();
Yes, I know that doesn't actually work.


public Modual Copy()
{
Modual T = null;
if (!Copying)
{
Copying = true;
T = (Modual)this.GetType(); // <-Something like this, but that actually works.
T.value = value;
foreach (Modual M in Inputs)
{
T.Inputs.Add(M.Copy());
}
Copying = false;
}
return T;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Grain
So is there no way to dynamically determine type at runtime and get different behavior....


I believe you're writing in Java, right? In Java the answer to your question is yes. I've never done it, so I can't provide details off the top of my head, but just google "java reflection example" or something like that.

Share this post


Link to post
Share on other sites
I don't know much about C#, but you can probably do something analogous to reflection in Java. Let's see ... yeah, read this:

http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx

[Edited by - jwezorek on December 4, 2009 5:51:32 PM]

Share this post


Link to post
Share on other sites
Oh wow, that's it!

Instead of using T = Copy(); I can now do T = (Modual)System.Reflection .Activator.CreateInstance(this.GetType()):

Now I don't have to implement Copy() for all those subclasses. =)

Share this post


Link to post
Share on other sites
Not sure if it’s important or not but I don’t see how you’re Clone/Copy functions actually "Clone" the object. How does the base class correctly copy the data members in the derived classes? Your implementation only initializes data members declared in the base class.

Share this post


Link to post
Share on other sites
After thinking about it what you really want is to define copy constructors for all your classes and then implement clone like this:


public Base Clone()
{
object[] param = new object[] { this };

return System.Activator.CreateInstance(this.GetType(), param) as Base;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Scythen
Not sure if it’s important or not but I don’t see how you’re Clone/Copy functions actually "Clone" the object. How does the base class correctly copy the data members in the derived classes? Your implementation only initializes data members declared in the base class.


Most of the derived classes don't have data members that are important to save. These objects are highly dynamic and their data is in a constant state of change.
What is important is the layout of the composite object and the types of its elements. That is what is copied by the base class.


Quote:
Original post by Scythen
After thinking about it what you really want is to define copy constructors for all your classes and then implement clone like this:


No that isn't what I want. That's very similar to what I had. The point was to avoid having to re-implement the same function in every single derived class.

Share this post


Link to post
Share on other sites
Ok, that was just my two cents.

Copying all the data may not be what you want and that’s fine but implementing a copy constructor is not the same as reimplementing the same function in every class. Generally when you will be copying objects you want copy constructors.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement