I've been doing some reading on the Strategy Pattern, and have a question. I have implemented a very basic Console Application below to explain what I'm asking.
I have read that having 'switch' statements is a red flag when implementing the strategy pattern. However, I can't seem to get away from having a switch statement in this example. Am I missing something? I was able to remove the logic from the Pencil, but my Main has a switch statement in it now. I understand that I could easily create a new TriangleDrawer class, and wouldn't have to open the Pencil class, which is good. However, I would need to open Main so that it would know which type of IDrawer to pass to the Pencil. Is this just what needs to be done if I'm relying on the user for input? If there's a way to do this without the switch statement, I'd love to see it!
class Program
{
public class Pencil
{
private IDraw drawer;
public Pencil(IDraw iDrawer)
{
drawer = iDrawer;
}
public void Draw()
{
drawer.Draw();
}
}
public interface IDraw
{
void Draw();
}
public class CircleDrawer : IDraw
{
public void Draw()
{
Console.Write("()\n");
}
}
public class SquareDrawer : IDraw
{
public void Draw()
{
Console.WriteLine("[]\n");
}
}
static void Main(string[] args)
{
Console.WriteLine("What would you like to draw? 1:Circle or 2:Sqaure");
int input;
if (int.TryParse(Console.ReadLine(), out input))
{
Pencil pencil = null;
switch (input)
{
case 1:
pencil = new Pencil(new CircleDrawer());
break;
case 2:
pencil = new Pencil(new SquareDrawer());
break;
default:
return;
}
pencil.Draw();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
Implemented Solution shown below (Thanks to all who responded!)
This solution got me to the point where the only thing I need to do to use a new IDraw object is to create it.
public class Pencil
{
private IDraw drawer;
public Pencil(IDraw iDrawer)
{
drawer = iDrawer;
}
public void Draw()
{
drawer.Draw();
}
}
public interface IDraw
{
int ID { get; }
void Draw();
}
public class CircleDrawer : IDraw
{
public void Draw()
{
Console.Write("()\n");
}
public int ID
{
get { return 1; }
}
}
public class SquareDrawer : IDraw
{
public void Draw()
{
Console.WriteLine("[]\n");
}
public int ID
{
get { return 2; }
}
}
public static class DrawingBuilderFactor
{
private static List<IDraw> drawers = new List<IDraw>();
public static IDraw GetDrawer(int drawerId)
{
if (drawers.Count == 0)
{
drawers = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => typeof(IDraw).IsAssignableFrom(type) && type.IsClass)
.Select(type => Activator.CreateInstance(type))
.Cast<IDraw>()
.ToList();
}
return drawers.Where(drawer => drawer.ID == drawerId).FirstOrDefault();
}
}
static void Main(string[] args)
{
int input = 1;
while (input != 0)
{
Console.WriteLine("What would you like to draw? 1:Circle or 2:Sqaure");
if (int.TryParse(Console.ReadLine(), out input))
{
Pencil pencil = null;
IDraw drawer = DrawingBuilderFactor.GetDrawer(input);
pencil = new Pencil(drawer);
pencil.Draw();
}
}
}
Strategy isn't a magic anti-switch solution. What it does do is give modularise your code so that instead of a big switch and business logic all mixed up in a maintenance nightmare
your business logic is isolated and open for extension
you have options as for how you create your concrete classes (see Factory patterns for example)
your infrastructure code (your main) can be very clean, free of both
For example - if you took the switch in your main method and created a class which accepted the command line argument and returned an instance of IDraw (i.e. it encapsulates that switch) your main is clean again and your switch is in a class whose sole purpose is to implement that choice.
I don't think your switch here in your demo app is actually part of the strategy pattern itself, it is just being used to exercise the two different strategies you have defined.
The "switches being a red flag" warning refers to having switches inside the strategy; for example, if you defined a strategy "GenericDrawer", and had it determine if the user wanted a SquareDrawer or CircleDrawer internally using a switch against a parameter value, you would not be getting the benefit of the strategy pattern.
The following is an over engineered solution to your problem solely for the sake of avoiding if/switch statements.
CircleFactory: IDrawFactory
{
string Key { get; }
IDraw Create();
}
TriangleFactory: IDrawFactory
{
string Key { get; }
IDraw Create();
}
DrawFactory
{
List<IDrawFactory> Factories { get; }
IDraw Create(string key)
{
var factory = Factories.FirstOrDefault(f=>f.Key.Equals(key));
if (factory == null)
throw new ArgumentException();
return factory.Create();
}
}
void Main()
{
DrawFactory factory = new DrawFactory();
factory.Create("circle");
}
You can also get rid of if with help of a dictionary
Dictionary<string, Func<IDraw> factory> drawFactories = new Dictionary<string, Func<IDraw> factory>() { {"circle", f=> new CircleDraw()}, {"square", f=> new SquareDraw()}}();
Func<IDraw> factory;
drawFactories.TryGetValue("circle", out factory);
IDraw draw = factory();
A little to late but for anyone that still is interested in fully removing a conditional statement.
class Program
{
Lazy<Dictionary<Enum, Func<IStrategy>>> dictionary = new Lazy<Dictionary<Enum, Func<IStrategy>>>(
() =>
new Dictionary<Enum, Func<IStrategy>>()
{
{ Enum.StrategyA, () => { return new StrategyA(); } },
{ Enum.StrategyB, () => { return new StrategyB(); } }
}
);
IStrategy _strategy;
IStrategy Client(Enum enu)
{
Func<IStrategy> _func
if (dictionary.Value.TryGetValue(enu, out _func ))
{
_strategy = _func.Invoke();
}
return _strategy ?? default(IStrategy);
}
static void Main(string[] args)
{
Program p = new Program();
var x = p.Client(Enum.StrategyB);
x.Create();
}
}
public enum Enum : int
{
StrategyA = 1,
StrategyB = 2
}
public interface IStrategy
{
void Create();
}
public class StrategyA : IStrategy
{
public void Create()
{
Console.WriteLine("A");
}
}
public class StrategyB : IStrategy
{
public void Create()
{
Console.WriteLine("B");
}
}
Related
I am trying to make a decorator Logging class for two classes of the same interface type, that would take the class and basically override its method step so it could print some extra things. I found this solution really bad because I am reimplementing things that are already implemented but I can't think of a better solution.
public class A :IA
{
private int state = 0;
public void printStep()
{
Console.WriteLine("A state: {0}", state);
}
public bool Step()
{
state++;
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : IA
{
private double state = 0.0;
public void printStep()
{
Console.WriteLine("B state: {0}", state);
}
public bool Step()
{
state+= 0.1;
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
public void Run() //Don't like this method especially because it shouldn't reimplement the run methods again
{
if (ia.GetType() == typeof(A))
{
for (int i = 0; i < 5; ++i)
{
ia.printStep();
ia.Step();
}
}
else
{
for (int i = 0; i < 4; ++i)
{
ia.printStep();
ia.Step();
}
}
}
}
Any ideas how to do this?
EDIT: what I would like to do is something like this
public override bool Step()
{
var ret = base.Step();
base.printStep();
return ret;
}
EDIT 2: I need to call the original Run method that would be calling an updated Step method with the added logging. Expected behavior from this simple example would be Logger of class A would print symbol A 5 times and Logger of class B would print symbol B 4 times.
EDIT 3: Why I am trying to do this kind of behavior? What I felt like is having two classes A and B that would be fully working without writing any information on its own. The Logger should take either of them and log every state that would usually change after each step. So I would get a perfect information. I could play with something like adding a boolean variable logging in the A and B classes but it just doesn't feel right.
public class A :IA
{
...
public bool Step()
{
if (logging) printStep();
state++;
return true;
}
...
EDIT 5: Changed the initial code so it makes more sense.
Use:
var a = new A();
a.Run();
var b = new B();
b.Run();
var loggerA = new Logger(a);
loggerA.Run();
var loggerB = new Logger(b);
loggerB.Run();
Expected output:
A state: 5
A state: 6
A state: 7
A state: 8
A state: 9
B state: 0.4
B state: 0.5
B state: 0.6
B state: 0.7
If you want the Logger class to implement the Decorator pattern, it must implement the same interface as the "decorated" classes (not just to encapsulate them as in your snippet).
By doing so you'll be able to achieve the desired behavior (similar to the one in your EDIT).
EDIT:
Assuming that this is the responsibility of the Logger to log something, IA doesn't have to contain the printStep() method.
Thus we have:
public interface IA
{
bool Step();
}
public class A : IA
{
public bool Step()
{
return true;
}
}
public class B : IA
{
public bool Step()
{
return true;
}
}
public class Logger : IA
{
private readonly IA _decorated;
public Logger(IA decorated)
{
_decorated = decorated;
}
public bool Step()
{
Console.WriteLine("Before Step...");
_decorated.Step();
Console.WriteLine("Step completed.");
}
}
When instantiating the Logger you need to pass the object you want to decorate
IA notDecorated = new A();
IA decorated = new Logger(notDecorated);
If you want to get rid of the shared functionality in A and B you can make an abstract class. Implement the shared functionality here and make the remaining methods abstract. If you strictly want to use the decorator pattern you could make an interface for the abstract class.
public class A : AbstractA
{
public override void printStep()
{
Console.WriteLine("A");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : AbstractA
{
public override void printStep()
{
Console.WriteLine("B");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public abstract class AbstractA : IA
{
public abstract void printStep();
public virtual bool Step()
{
return true;
}
public virtual void Run()
{
printStep();
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
void Run()
{
ia.Run();
}
}
If there's not a reason for other objects to be calling Step() directly it shouldn't be part of the interface. However, since I think you're making classes that may be mostly similar in shape but potentially very different in implementation, I don't think decorating these classes will get you what you want. I think it makes more sense to just add in logging where it's needed.
I included a toy example of what a modern logging framework (like NLog) does for you. In my example, you can change whether or not you have logging by passing in a different logging implementation. In a real framework, you have different levels of logging that you can configure so that you can turn off logging completely or only log more important information.
public class A : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
// some logic
logger.Info("Something specific here.")
// more logic
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
logger.Info("A");
Step();
}
}
}
public class B : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
logger.Info("B");
Step();
}
}
}
public interface IA
{
void Run();
}
public interface ILog
{
void Info(string message);
}
public class ConsoleLogger : ILog
{
public void Info(string message)
{
Console.WriteLine(message);
}
}
public class NoopLogger : ILog
{
public void Info(string message)
{
}
}
Then when you instantiate your classes, you can pass in whatever logger you need.
var noopLogger = new NoopLogger();
var a = new A(noopLogger);
a.Run();
var b = new B(noopLogger);
b.Run();
var consoleLogger = new ConsoleLogger();
a = new A(consoleLogger);
a.Run();
b = new B(consoleLogger);
b.Run();
How to solve this problem about interfaces? I think I need this variable (and some others)in this especific class.
public interface Action
{
void execute();
}
public A:Action
{
public int misteriousNumber;
void execute()
{
int iUseMisteriousNumber = misteriousNumber;
}
}
public B:Action
{
void execute()
{
//I use nothing.
}
}
//Some Class...
static void Main(string[] args)
{
foreach(Action action in SecretRepositoryOfTheActions.actions)
{
if(action is A)
(SomeTypeOfCasting to A)action.misteriousNumber=13;
action.execute();
}
}
Just the 'A' class have this property not other Action classes what to use to access it (casting, not interfaces other implementation)?
You have to cast it, first check the type with is:
foreach(Action action in SecretRepositoryOfTheActions.actions)
{
if(action is A)
((A) action).misteriousNumber = 13;
action.execute();
}
If you only wanted to process A-objects (which doesn't seem to be the case):
foreach(A a in SecretRepositoryOfTheActions.actions.OfType<A>())
{
a.misteriousNumber = 13;
a.execute();
}
I've found some code that is a bit long in a method:
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
if (item is Son) {
...SOME CODE...
}
else if (item is Daughter) {
...MORE CODE...
}
}
}
}
Because of this big if-else block, the method is quite large, and smells as bad design (OOP-wise).
I've tried to come up with something a bit more polymorphic, taking advantage of method-overloading via different type-paramaters, such as:
class MainClass
{
private static void DoSomething (Son son)
{
Console.WriteLine ("Son");
}
private static void DoSomething (Daughter daughter)
{
Console.WriteLine ("Daughter");
}
private static void DoSomething (Parent parent)
{
Console.WriteLine ("Parent");
}
private void Iterate(IEnumerable<Parent> list)
{
foreach (var item in list) {
DoSomething (item);
}
}
}
But this doesn't work because it always prints "Parent", so I guess I would need to downcast manually, which defeats the point a bit, and would not look elegant.
One last point: if you are tempted to recommend me to put the implementation of DoSomething in the derived classes of Parent, that is not possible, because of dependency problems (the assembly where these 3 classes live cannot have dependencies on some things that the SOME CODE and MORE CODE is calling).
So what would be the best approach to refactor this? Thanks!
There are several ways to do this asides from the switch statement you've already identified (which definitely gets clunky with more than a couple of types involved).
First of all, if you aren't likely to add subtypes, but you are likely to add other things to do with the subtypes, you can use the Visitor Pattern to mimic double dispatch.
class Parent
{
public abstract void Accept(IChildVisitor visitor);
}
class Son : Parent
{
public override void Accept(IChildVisitor visitor)
{
visitor.Visit(this);
}
}
class Daughter : Parent
{
public override void Accept(IChildVisitor visitor)
{
visitor.Visit(this);
}
}
interface IChildVisitor
{
Visit(Son son);
Visit(Daughter daughter);
}
class SomeCodeChildVisitor : IChildVisitor
{
public Visit(Son son)
{
...SOME CODE...
}
public Visit(Daughter daughter)
{
...SOME CODE...
}
}
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
item.Accept(new SomeCodeChildVisitor());
}
}
}
You can also use a Dictionary<Type,Action>
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
// If you don't actually need a reference to the child
private void IDictionary<Type, Action> map =
new Dictionary<Type, Action>()
{
{ typeof(Son), () => ...SOME CODE... }
{ typeof(Daughter), () => ...SOME CODE... }
};
// If you do need a reference to the child
private void IDictionary<Type, Action<Parent>> otherMap =
new Dictionary<Type, Action<Parent>>()
{
{ typeof(Son), x => (Son)x. ...SOME CODE... }
{ typeof(Daughter), y => (Daughter)x. ...SOME CODE... }
};
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
// either
map[item.GetType()]();
// or
otherMap[item.GetType()](item);
}
}
}
You can also use the dynamic keyword
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
Visit((dynamic)item);
}
}
private void Visit(Son son)
{
...SOME CODE...
}
private void Visit(Daughter daughter)
{
...SOME CODE...
}
}
You can also just filter the types straight out of your collection with Linq (especially if you only care about some subtypes and not others, e.g. if you're iterating through a Controls collection and you only care about Buttons)
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Daughter daughter in list.OfType<Daughter>()) {
...SOME CODE...
}
}
}
In C# I generally recommend the dictionary approach, but any will do in a pinch.
The best situation is to move DoSomething() method to the classes. If not possible, maybe you still can use conditionals to polymorphism, but with the decorator pattern. In this case you can
Define an abstract class with an abstract method DoSomething(). Let's call it FamilyDecorator. It's a good idea to create a constructor which receives a Parent in his parameter, so you can save it as a protected variable (that means: visible to all of the derived classes).
Declare one decorator for each class on your assembly: ParentDecorator, SonDecorator, DaughterDecorator. These three classes inherit from FamilyDecorator and must override the DoSomething() method.
The trick is to create a method in the abstract class that returns one or another Decorator, based on type. That's the way you can separate which logic use on each case:
abstract class FamilyDecorator
{
protected Domain.Parent _member;
public abstract void DoSomething();
internal FamilyDecorator(Domain.Parent member)
{
_member = member;
}
public static FamilyDecorator GetDecorator(Domain.Parent item)
{
if(item.GetType() == typeof(Domain.Parent))
{
return new ParentDecorator(item);
}
else if (item.GetType() == typeof(Domain.Son))
{
return new SonDecorator(item);
}
else if (item.GetType() == typeof(Domain.Daughter))
{
return new DaughterDecorator(item);
}
return null;
}
}
class ParentDecorator : FamilyDecorator
{
internal ParentDecorator(Domain.Parent parent)
: base(parent)
{
}
public override void DoSomething()
{
Console.WriteLine("A parent");
}
}
class SonDecorator : FamilyDecorator
{
internal SonDecorator(Domain.Parent son)
: base(son)
{
this._member = son;
}
public override void DoSomething()
{
Console.WriteLine("A son");
}
}
class DaughterDecorator : FamilyDecorator
{
internal DaughterDecorator(Domain.Parent daughter)
: base(daughter)
{
}
public override void DoSomething()
{
Console.WriteLine("A daughter");
}
}
Then, in your Main class:
foreach (Parent item in list)
{
var decorator = FamilyDecorator.GetDecorator(item);
decorator.DoSomething();
}
This solution keeps the code very clean and takes advantage of polymorphism.
Edit
I don't think I like this solution because you're basically moving the
type checking from the foreach loop to the GetDecorator() method.
Polymorphism should allow you to do this without type checking
manually.
There is another solution, based on the same idea: to use reflection for the object construction.
In this case:
Instead of an abstract class you define an Interface that declares the DoSomething() method.
Now each decorator inherits from their corresponding class (Parent - ParentDecorator, Son - SonDecorator, etc.)
You need to change the constructors in the Decorator classes. They need to be public if you want to use reflection.
Finally, the GetDecorator() method just search for the derived class in the assembly. If found, it returns the decorator.
namespace FamilyNamespace
{
interface IFamily
{
void DoSomething();
}
class ParentDecorator : Domain.Parent, IFamily
{
private Domain.Parent _member;
public ParentDecorator(Domain.Parent parent)
{
this._member = parent;
}
public void DoSomething()
{
Console.WriteLine("A parent");
}
}
class SonDecorator : Domain.Son, IFamily
{
private Domain.Parent _member;
public SonDecorator(Domain.Parent son)
{
this._member = son;
}
public void DoSomething()
{
Console.WriteLine("A son");
}
}
class DaughterDecorator : Domain.Daughter, IFamily
{
private Domain.Parent _member;
public DaughterDecorator(Domain.Parent daughter)
{
this._member = daughter;
}
public void DoSomething()
{
Console.WriteLine("A daughter");
}
}
}
Then in your Main class:
static FamilyNamespace.IFamily GetDecorator(Domain.Parent item)
{
var baseType = item.GetType();
var derivedType = Assembly.GetExecutingAssembly().GetTypes().Where(m => m != baseType && baseType.IsAssignableFrom(m));
if (derivedType.Any())
{
return (FamilyNamespace.IFamily)Activator.CreateInstance(derivedType.First(), new object[] { item });
}
return null;
}
... and the Main method:
foreach (Domain.Parent item in list)
{
var decorator = (FamilyNamespace.IFamily)GetDecorator(item);
decorator.DoSomething();
}
Greetings
I am working on some code whereby I have an abstract class that has a few core properties and a Run(int index) method. I then create new types that inherit this. These new types can have multiple methods that can be called according to the index passed in.
public abstract class BaseClass
{
public abstract void Run(int index);
}
public class Class1 : BaseClass
{
public override void Run(int index)
{
if (index == 0)
{
MethodA();
}
else if (index == 1)
{
MethodB();
}
}
private void MethodA()
{
//do stuff
}
private void MethodB()
{
//do stuff
}
}
I'm just wondering is there a better way to do this. These types and methods would be called from a UI, - a menu click for example. So I might have a class1 and a class2. Class1 might have 3 methods so I could call run(0) ... run(2) on it. Class2 might just have one internal method so I would just call run(0). Maybe I would need to keep a collection of ints with each class I guess as a map to methods. Might also have to add a string to this collection to hold a friendly name for menu items etc..
Can you think of a way to implement this type of mapping while maintaining as much abstraction as possible? Is there a better way to go about this that my current idea?
One way:
You could use an interface instead:
public interface IRunnableSomething {
void Run();
}
public class MyRunnableA :IRunnableSomething
{
public void Run() {
// do stuff
}
}
public class MyRunnableB :IRunnableSomething
{
public void Run() {
// do stuff
}
}
Then in your main class...
public override void Run(IRunnable runnable)
{
runnable.Run();
}
Example of calling it:
myInstanceOfMainClass.Run(new MyRunnableA());
This seems fitting, since you already know what index you were passing in with your original version. This just moves it from int based to interface based (less code too in the end).
Let me explain a bit further so. Here's a slightly more verbose version of what I am trying to do. You can see here that my abstract class has the list of indexes for pointing at the right method in derived classes, and you can see where I am loading types and creating menu items in a UI. I am using this ItemPointer list and passing around ItemPointers to tag properties etc. It all feels a bit wrong somehow.
I wish for the whole thing to be extensible. I might want to add a Class2, Class3 etc all inheriting BaseClass. I might also want to create plugins using BaseClass. Any derived class will have at least one but runable method but will likely have many. So Class1 here is just an example. Does this help explain myself? please go easy on me, I'm learning and that's why I am asking here.
Is what I'm doing here awful? or is it ok? or is there a better way? I guess that's my question. If there is a better way, I'd really appreciate an example. Many thanks to all for the help. It is much appreciated.
public abstract class BaseClass
{
public List<ItemPointer> ItemPointers = new List<ItemPointer>();
public abstract void Run(int index);
}
public class ItemPointer
{
public int Index { get; set; }
public string ClassType { get; set; }
public string UIDescription { get; set; }
}
public class Class1 : BaseClass
{
public Class1()
{
ItemPointers.Add(new ItemPointer { Index = 0, ClassType = this.GetType().Name, UIDescription = "MethodA Description" });
ItemPointers.Add(new ItemPointer { Index = 1, ClassType = this.GetType().Name, UIDescription = "MethodB Description" });
}
public override void Run(int index)
{
if (index == 0)
{
MethodA();
}
else if (index == 1)
{
MethodB();
}
}
private void MethodA()
{
//do stuff
}
private void MethodB()
{
//do stuff
}
}
public class UIForm
{
private List<BaseClass> _baseClasses;
//Formload events load all baseclass types (including plugins via reflection during form init etc. Then call loadUIitems
private void LoadUIItems()
{
foreach (BaseClass bc in _baseClasses)
{
foreach (var p in bc.ItemPointers)
{
ToolStripMenuItem t = new ToolStripMenuItem(p.UIDescription);
t.Click += new EventHandler(WorkerMenu_Click);
t.Tag = p;
actionsToolStripMenuItem.DropDownItems.Add(t);
}
}
}
void WorkerMenu_Click(object sender, EventArgs e)
{
ToolStripMenuItem t = (ToolStripMenuItem)sender;
ItemPointer p = (ItemPointer)t.Tag;
foreach (BaseClass bc in _baseClasses)
{
if (bc.GetType().Name == p.ClassType)
{
bc.Run(p.Index);
}
}
}
}
In your position I might be inclined to try do something like this:
void Main()
{
var a = new Class1();
var b = new Class2();
try
{
a.Run("Foo");
b.Run("Bar", "Yoda");
b.Run("Bat"); // throws exception
}
catch (Exception ex)
{
Console.WriteLine (ex.Message);
}
}
class Base
{
public void Run(string commandName, params object[] args)
{
var method = this.GetType().GetMethod(commandName);
if(method != null)
method.Invoke(this, args);
else
throw new Exception("the command " + commandName + " does not exist on " + this.GetType().Name);
}
}
class Class1 : Base
{
public void Foo()
{
Console.WriteLine ("I am foo");
}
}
class Class2 : Base
{
public void Bar(string str)
{
Console.WriteLine ("I am {0}", str);
}
}
Output:
I am foo
I am Yoda
the command Bat does not exist on Class2
Hi I'm new to OOP and I need help on a little problem.
I used a collection called Monsters to store 3 types of object. Spiders, Farmers, Gollum(irrelevant).
My collection as an indexer but when I use it to get an object out of the collection the object is typeless but I really need to TypeCast my next opperation.
private void Form1_Load(object sender, EventArgs e)
{
CurrentOpponent Opponent = new CurrentOpponent();
Gollum myGollum = new Gollum();
AngryFarmer myFarmer = new AngryFarmer();
Ugly_Spider mySpider = new Ugly_Spider();
myMonsters.AddGollum(myGollum);
myMonsters.AddFarmer(myFarmer);
myMonsters.AddUgly(mySpider);
progressBar1.Increment(100);
progressBar2.Increment(100);
Monster myCurrentOpponent = Opponent.randomEncounter();
//textBox1.Text = (this is where i need the type for a cast)myCurrentOpponent.name
}
Here is the randomEncounter where i extract the object
class CurrentOpponent
{
public Monster randomEncounter()
{
Random _random = new Random();
int opp = _random.Next(4);
return myMonsters[opp];
}
And finally the indexer wich returns a monster (parent of all 3 monster types)
public Monster this[int xxx]
{
get
{
return (Monster)List[xxx];
}
}
Help would be really appreciated..!!
Thanks in advance
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit from Monster:
public class AngryFarmer : Monster
{
// ...
}
// etc.
You could then just use a List<Monster>:
myMonsters = new List<Monster>();
myMonsters.Add(new AngryFarmer()); // works because AngryFarmer is a kind of Monster
This will allow you to use polymorphism.
you need to use interfaces...... IMonster..... IMonster then has a name
then make all your monsters implement IMonster
and just have a List of IMonsters
you may wanna try it by using interfaces also! have a look...
public interface IMonster
{
String Name { get; }
Int32 Health { get; set; }
}
public class Spider : IMonster
{
public Spider()
{
_health = 100;
}
public string Name
{
get { return "Spider"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
public class Gollum : IMonster
{
public Gollum()
{
_health = 250;
}
public string Name
{
get { return "Gollum"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
class Program
{
static void Main(string[] args)
{
List<IMonster> monsters = new List<IMonster>()
{
new Gollum(),
new Spider()
};
IMonster randomMonster = GetRandomMonster(monsters);
Console.WriteLine(randomMonster.Name + "/" + randomMonster.Health);
}
private static IMonster GetRandomMonster(List<IMonster> monsters)
{
//Your code for getting a random monster goes here!
throw new NotImplementedException();
}
}
I like very much this approach... Imagine you have an element on your game that initially is not exactly a monster. Say it is a random element on your game that after a given event it becomes a monster that your Hero (say a game like heroes of mighty and magic) have to fight with. If you decided to add this feature long time after you created the game, it would become harmful/difficult/risky to change it, as this element might have already be inheriting from another class. If you were using interfaces you would simply implement it on this entity and it would promptly be capable of behaving like any other IMonster in your game. It means that this random entity would be able to be passed as a param to the method Fight(IHero hero, IMonster monster);
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit
from Monster
I have learn your problem like the problem in the Tetris game:
1/ You have Monsters like I have Shapes.
2/ Each kind of Monster have it own properties (Health, Magic Point,...) and behaviours (attack, run, cast spell,..) like the Blocks have properties (color, position, state,..) and
behaviours (go down, rotate right, rotate left,...)
In the scene of the game you want to random a Monster that have the specific properties and behaviours, like I want to random a Shape. If it is your problem you can try my code:
public abstract class CMonster
{
int _HP;
int _MP;
//..and something like this
public int HP
{
get { return this._HP; }
set { this._HP=value;}
}
public int MP
{
get { return this._MP; }
set { this._MP = value; }
}
public abstract void Run();
public abstract void Attach();
public abstract void CastSpell();
}
public class CUgly_Spider : CMonster
{
public CUgly_Spider()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
public class CGollum : CMonster
{
public CGollum()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
class Test
{
private void InitTheGame()
{
CMonster curMonster=null;
Random rnd = new Random();
//sample random
if ((rnd.Next() % 2) == 0)
{
curMonster = new CGollum();
}
else
{
curMonster = new CUgly_Spider();
}
curMonster.Run();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.Attach();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.CastSpell();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
}
}
I hope that can help you.