I'm trying to design a few classes for a game, but I'm not sure I'm doing it right.
I have two classes: Actor and Building.
These have a few subclasses: Policeman, Fireman and PoliceStation, FireStation.
I want to be able to put all these items together in a list to iterate through later, so I've added a base class: GameEntity.
So what I have is this:
public abstract class GameEntity:
{
public GameEntity()
{
}
}
public class Actor: GameEntity
{
public int _speed;
public TileSprite _UI;
public Actor()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoActing()
{
}
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
}
public class Building: GameEntity
{
public TileSprite _UI;
public Building()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoBuilding()
{
}
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
}
Now, I want to be able to do this:
List<GameEntity> Entities = new List<GameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation
Entities.Add(a1);
Entities.Add(b1);
foreach(GameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
//If Actor then do
ent.DoActing();
//If Building then do
ent.DoBuilding();
}
}
Now, in order to do the last bit, would it be best if I implement an interface that contains the OnClick and CollidesWith, or can I do it with inheritance?
If so, how would I do this?
Cheers.
This is only to give you the idea, I guess that's what you need.
public interface IGameEntity
{
bool CollidesWith();
void OnClick();
void DoActing();
}
public class Actor : IGameEntity { //Interface implemented }
public class Building: IGameEntity { //Interface implemented }
public class Policeman: IGameEntity { //Interface implemented }
public class Fireman: IGameEntity { //Interface implemented }
public class FireStation: IGameEntity { //Interface implemented }
In your client object just do something like this:
List<IGameEntity> entities = new List<IGameEntity>()
{
new Actor(),
new Building(),
new Policeman(),
new Fireman(),
new Fireman()
};
foreach (IGameEntity entity in entities)
{
entity.CollidesWith();
entity.OnClick();
entity.DoActing();
}
Number of ways to go here.
If all GameEntities can be clicked on then you could add an OnClick event property to the base class.
If Not then I'd have an Interface IClick and then implement that on clickable entities.
Collision, depends.
Building don't move about so they can't collide with anything, but they can be collided with and so for instance you might want do a damage rountine, which then suggests a destroyed, routine a repair routine maybe.
There's no right answer, but
Three code smells would be a
A Base class with nothing in it.
A very deep inheritance hierarchy (more than two levels is cause for suspicion in my book)
So if you start seeing GameEntity -> BuildingEntity -> ActiveBuildingEntity -> RepairableBuildingEntity, you are in a mess that's about to get messier.
And above all a base class with do nothing methods in it that only exist because you need to add behaviour (override) in some descendants.
Don't be scared about having a few interfaces. IClick, ICollision, IDamage, IRepair etc. It's way better than implying a building can crash into a car.
You could do something like this:
public interface IGameEntity
{
void OnClick();
bool CollidesWith(Vector2 pos);
void Do();
}
public abstract class Actor: IGameEntity
{
public int _speed;
public TileSprite _UI;
public virtual bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void OnClick();
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void Do();
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
//Do Acting for Police
}
}
public abstract class Building: IGameEntity
{
public TileSprite _UI;
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public abstract void OnClick();
public abstract void Do();
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
// Do Building
}
}
If Game Entity is just an interface then there is no need to make it an abstract class. If Actor and Building can never exist as a stand alone object then they should be abstract. If DoActing, DoBuilding, and OnClick must be overridden by the base classes then you can mark them abstract in actor and Building.
I followed norlesh's suggestion to just have one method Do. You could also make Actor and Building have their own abstract methods and IGameEntity would not have Do. Then you would put an if statement and check the if each object is of type builder then they would run the build and if of type actor then run act.
I think the way of having one method is better, since you eliminate one step. From a design perspective I'm not sure but it feels the same to me either way.
List<IGameEntity> Entities = new List<IGameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation();
Entities.Add(a1);
Entities.Add(b1);
foreach(IGameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
ent.Do();
}
}
Adding a virtual doStuff() to GameEntity and overriding it in the child classes instead of having unique method names like DoActing and DoBuilding then calling that from your loop should do what you want.
Related
I am trying to solve a simple OOPs problem. When I have to create few weapons and each weapon has a primary action and that primary action can be performed by a mouse click. Example for a shotgun it is shooting and for Katana is swinging it. Below my classes are.
public interface IShootable
{
void TakeShot();
}
public interface ISwingable
{
void Swing ();
}
public class ShotGun : IShootable
{
public void TakeShot()
{
}
}
public class Kanata : ISwingable
{
public void Swing ()
{
}
}
Each weapon has implemented different interface for their primary actions. (I'm not sure that I can create an abstract class, from which I can inherit these concrete classes. It seems not substitutable for two different type of weapons.)
What I wanted to achieve is in runtime when user selects one of the weapons, the user gets the right action on mouse click. For shotgun it is TakeShot() and for Katana it is Swing().
What I have to do adopt that. Or I should restructure the classes in some other way.
Both classes can both implement a third interface - IWeapon, with an Attack/Use method:
public interface IWeapon {
void Attack();
}
public class ShotGun : IShootable
{
void IWeapon.Attack() {
TakeShot();
}
public void TakeShot()
{
}
}
public class Kanata : ISwingable
{
public void Swing ()
{
}
void IWeapon.Attack() {
Swing();
}
}
Note that I have explicitly implemented the IWeapon interface here. You don't have to do it explicitly, and can still do it the "normal way". but I prefer it this way. This way, when you have a Katana object, only Swing is visible, but not Attack. I just feel that having both methods visible is confusing.
Also note that IWeapon is unrelated to ISwingable and IShootable, because swingable things (tennis racket) and shootable things (water pistol) are not necessarily weapons.
You might want to do something more generic:
public interface IWeaponPrimaryAction
{
void PerformPrimaryAction();
}
public interface IWeaponAction
{
void PrimaryAction();
}
public class Shoot :IWeaponAction
{
public void PrimaryAction()
{
//Fire in the hole
}
}
public class Swing :IWeaponAction
{
public void PrimaryAction()
{
//Into pieces
}
}
public class ShotGun : IWeaponPrimaryAction
{
private IWeaponAction _action = new Shoot();
public void PerformPrimaryAction()
{
_action.PrimaryAction();
}
}
public class Kanata : IWeaponPrimaryAction
{
private IWeaponAction _action = new Swing();
public void PerformPrimaryAction()
{
_action.PrimaryAction();
}
}
Better than that just inject the action:
public class ShotGun : IWeaponPrimaryAction
{
private IWeaponAction _action;
public ShotGun(IWeaponAction action)
{
_action = action;
}
public void PerformPrimaryAction()
{
_action.PrimaryAction();
}
}
My preference would be what #Riki suggests and create an interface that all weapons inherit IWeapon with a single method IWeapon.PerformPrimaryAction(). However if you don't like that you could create a "base" interface that all weapon interfaces derive from, then at runtime use casting, is or as to determine which weapon you have:
public interface IWeapon {};
public interface IShootable : IWeapon
{
void TakeShot();
}
public interface ISwingable : IWeapon
{
void Swing ();
}
public partial class YourGameClass
{
public void DoTheAction (IWeapon weapon)
{
if (weapon is IShootable)
(weapon as IShootable).TakeShot();
if (weapon is ISwingable)
(weapon as ISwingable).Swing();
}
}
Background info
I have a set of interfaces/classes as follows. For the sake of simplicity imagine more properties, collections etc.
interface IMaster
{
//Some properties
}
interface IB : IMaster
{
string PropOnA { get; set }
}
interface IC : IMaster
{
string PropOnB { get; set }
}
class B : IB
class C : IC
...
These contracts were designed to store data(which is held in a slightly different format in each case). There is a lot of code that uses these contracts to get the data, format it, process it, write etc.
We have developed an entire library that does not see the concrete implementations(B,C) of any of these contracts by inverting control and allow the user to use our 'default implementations' for each contract or just loading in their own. We have registry where the user can register a different implementation.
To this end I have implemented a kind of strategy pattern where there exists a strategy for each contract type based on the task at hand. For the sake of simplicity lets say the task is writing, in reality it is much more complicated.
interface IWriteStrategy
{
public Write(IMaster thing);
}
class WriterA : IWriteStrategy
class WriterB : IWriteStrategy
etc
The above concrete strategies are also never 'seen' in our library, the client must register their own implementation or our default version.
Design flaw??
I am not liking the cast in every strategy that is now necessary.
public classWriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IA thingA)
//do some work
}
}
public classWriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IB thingB)
//do some work
}
}
What we want to do is be able to loop through a list of IMaster objects and run some operations.
foreach(var thing in Things)
{
var strategy = GetStrategy(thing.GetType()); //this gets the strategy object from our `registry` if one exists
strategy.Execute(thing);
}
The above design allows this but there seems to be a flaw which I cant for the life of me spot a solution to. We have to cast to the specific interface within each strategy implementation.
I have tried with generics, but just cant seem to nail it.
Question
What would be a better way of designing this to avoid the cast but still be able to loop through a list of IMaster things and treat them the same? Or is the cast absolutely necessary here?
I am trying to follow a SOLID design but feel the cast is messing with this as the client implementing the strategies will have to do the cast in order to get anything to work within the Write method.
[Edit]
I have updated the classes implementing the IWriteStrategy.
If you rarely add new IMaster specializations, but often add new operations OR need to make sure operation providers (e.g writer) needs to support ALL specializations then the Visitor Pattern is a perfect fit.
Otherwise you basically need some kind of service locator & registration protocol to map operation providers/strategies to IMaster specializations.
One way you could do it is define generic interfaces such as IMasterWriter<T> where T:IMaster which can then be implemented like IBWriter : IMasterWriter<IB> which defines the mapping.
From that point you only need a mechanism that uses reflection to find a specific IMasterWriter implementor for a given type of IMaster and decide what to do if it's missing. You could scan assemblies early to detect missing implementations at boot rather than failing later too.
Maybe it is appropriate to use Strategy pattern and just give an implementation and execute it. Let me show an example.
interface IMaster
{
void ExecuteMaster();
}
class MasterOne : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master One");
}
}
class MasterTwo : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master Two");
}
}
and
interface IWriteStrategy
{
void Write(IMaster thing);
}
class WriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer A");
thing.ExecuteMaster();
}
}
class WriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer B");
thing.ExecuteMaster();
}
}
and code to execute:
static void Main(string[] args)
{
List<IWriteStrategy> writeStrategies = new List<IWriteStrategy>()
{
new WriterA(),
new WriterB()
};
List<IMaster> executes = new List<IMaster>()
{
new MasterOne(),
new MasterTwo()
};
for (int i = 0; i < writeStrategies.Count(); i++)
{
writeStrategies[i].Write(executes[i]);
}
}
what about this, you will have all your casts in one strategy factory method:
public interface IWriterStrategy
{
void Execute();
}
public class WriterA : IWriterStrategy
{
private readonly IA _thing;
public WriterA(IA thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnA);
}
}
public class WriterB : IWriterStrategy
{
private readonly IB _thing;
public WriterB(IB thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnB);
}
}
public static class WriterFactory
{
public static List<(Type Master, Type Writer)> RegisteredWriters = new List<(Type Master, Type Writer)>
{
(typeof(IA), typeof(WriterA)),
(typeof(IB), typeof(WriterB))
};
public static IWriterStrategy GetStrategy(IMaster thing)
{
(Type Master, Type Writer) writerTypeItem = RegisteredWriters.Find(x => x.Master.IsAssignableFrom(thing.GetType()));
if (writerTypeItem.Master != null)
{
return (IWriterStrategy)Activator.CreateInstance(writerTypeItem.Writer, thing);
}
throw new Exception("Strategy not found!");
}
}
public interface IMaster
{
//Some properties
}
public interface IA : IMaster
{
string PropOnA { get; set; }
}
public interface IB : IMaster
{
string PropOnB { get; set; }
}
public interface IC : IMaster
{
string PropOnC { get; set; }
}
public class ThingB : IB
{
public string PropOnB { get => "IB"; set => throw new NotImplementedException(); }
}
public class ThingA : IA
{
public string PropOnA { get => "IA"; set => throw new NotImplementedException(); }
}
public class ThingC : IC
{
public string PropOnC { get => "IC"; set => throw new NotImplementedException(); }
}
internal static class Program
{
private static void Main(string[] args)
{
var things = new List<IMaster> {
new ThingA(),
new ThingB()//,
//new ThingC()
};
foreach (var thing in things)
{
var strategy = WriterFactory.GetStrategy(thing); //this gets the strategy object from our `registry` if one exists
strategy.Execute();
}
}
}
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
Good day,
I have a base class with a virtual method that needs to be overridden per implementation, but I would like to call the base method first before overriding.
Is there a way to accomplish this without having to actually call the method.
public class Base
{
public virtual void Method()
{
//doing some stuff here
}
}
public class Parent : Base
{
public override void Method()
{
base.Method() //need to be called ALWAYS
//then I do my thing
}
}
I cannot always rely that the base.Method() will be called in the override, so I would like to enforce it somehow. This might be a design pattern of some kind, any approach to accomplish the result will do.
One way is to define a public method in the base class, which calls another method that can be (or must be) overridden:
public class Base
{
public void Method()
{
// Do some preparatory stuff here, then call a method that might be overridden
MethodImpl()
}
protected virtual void MethodImpl() // Not accessible apart from child classes
{
}
}
public class Parent : Base
{
protected override void MethodImpl()
{
// ToDo - implement to taste
}
}
You can use the decorator design pattern, applying this pattern you can attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality:
public abstract class Component
{
public abstract void Operation();
}
public class ConcreteComponent1 : Component
{
public override void Operation()
{
//logic
}
}
public abstract class ComponentDecorator : Component
{
protected readonly Component Component;
protected ComponentDecorator(Component component)
{
Component = component;
}
public override void Operation()
{
if(Component != null)
Component.Operation();
}
}
public class ConcreteDecorator : ComponentDecorator
{
public ConcreteDecorator(Component component) : base(component)
{
}
public override void Operation()
{
base.Operation();
Console.WriteLine("Extend functionality");
}
}
Hope this helps!
I have a child class Bicycle that inherits from Agent. The agent has a property which depends on the bicycle to define it. Namely, the physics model for the agent needs to be initialised with the velocity and acceleration constraints which are defined on a per-bicycle-basis and would be different for another type of agent.
The problem I have is that I cannot pass the parameters I need to calculate (the velocity/acceleration require calculations to draw them from a theoretical distribution) for this in the base() constructor because of course the child class hasn't yet been instantiated.
The calculations are done once per bicycle instance but are used multiple times so a simple static method won't do the job. I can just call a protected method in the parent after they're calculated but AFAIK there's no way to enforce this in the child, or more particularly in any future children which I might not write.
So for example, I could:
public abstract class Agent
{
protected IPhysics PluginPhysics { get; set; }
protected Agent(...)
{
}
}
public class Bicycle : Agent
{
private double maxA;
public Bicycle(Object anotherParameter) : base(...)
{
maxA = ComputationOfMaxA();
this.PluginPhysics = new Physics(anotherParameter, maxA);
}
private static double ComputationOfMaxA()
{
...
}
...
}
or I could:
public abstract class Agent
{
protected IPhysics PluginPhysics { get; private set; }
protected Agent(...)
{
}
protected void SetupPhysics(Physics physics)
{
this.PluginPhysics = physics;
}
}
public class Bicycle : Agent
{
private double maxA;
public Bicycle(Object anotherParameter) : base(...)
{
maxA = ComputationOfMaxA();
SetupPhysics(new Physics(anotherParameter,maxA));
}
private static double ComputationOfMaxA()
{
...
}
...
}
I'd rather not do either of those as there's no compile-time way to ensure that the child initialises PluginPhysics that I can think of, and I'd rather PluginPhysics not be able to be changed once it's been initialised. I'd also rather not have the parts of the parameters that need to go into Physicsoutside the Bicycle class. I appreciate that all these things might not be simultaneously possible.
So short of strongly worded documentation or a bunch of run-time null checks in the parent class before any of the relevant class objects are called on, is there an obvious C#-ish way I'm missing of forcing a child to initialise a parent class field before use if you can't do it in the constructor?
d4Rk's answer was very close, however you should try not call virtual methods from a constructor as bad things can happen. However if you use a combination of Lazy loading tricks and ISupportInitialize you can defer the creation of the plugin till after the constructor is finished.
public abstract class Agent : ISupportInitialize
{
private bool _initialized = false;
private IPhysics _pluginPhysics;
protected IPhysics PluginPhysics
{
get
{
if(!_initialized)
EndInit();
return _pluginPhysics;
}
}
protected Agent(...)
{
}
protected abstract IPhysics CreatePhysics();
ISupportInitialize.BeginInit()
{
//We make this a explicit implementation because it will not
//do anything so we don't need to expose it.
}
public void EndInit()
{
if(_initialized)
return;
_initialized = true;
_pluginPhysics = CreatePhysics();
}
}
public class Bicycle : Agent
{
private double maxA;
Object _anotherParameter;
public Bicycle(Object anotherParameter)
{
_anotherParameter = anotherParameter;
}
protected override IPhysics CreatePhysics()
{
ComputationOfMaxA();
return new Physics(anotherParameter, maxA);
}
}
The user of your class will need to call EndInit() after they get a object back to cause the IPhysics object to be created, however if they forget to call the initialize function the getter on the physics object will trigger the initialize call itself the first time it is used.
You could do everything I have shown without the ISupportInitialize interface and just having a public Initalize() method on the base class but I like to expose framework interfaces when they fit.
What about enforcing the subclass to implement a CreatePhysics method, and call this in the base ctor?
Like this:
public abstract class Agent
{
protected IPhysics PluginPhysics { get; private set; }
protected Agent(...)
{
var physics = CreatePhysics();
SetupPhysics(physics);
}
void SetupPhysics(IPhysics physics)
{
this.PluginPhysics = physics;
}
protected abstract IPhysics CreatePhysics();
}
public class Bicycle : Agent
{
private double maxA;
protected override IPhysics CreatePhysics()
{
ComputationOfMaxA();
return new Physics(maxA);
}
}
How about making the constructor for Agent take the IPhysics object and making it protected Then in your Bicycle class, you are forced to call the constructor on the base which sets up your class property:
public class Agent
{
protected IPhysics PluginPhysics { get; private set; }
protected Agent(IPhysics physicsPlugin)
{
PluginPhysics = physicsPlugin;
}
}
public class Bicycle : Agent
{
public Bicycle(IPhysics physicsPlugin)
: base(physicsPlugin)
{
Console.WriteLine("Bicycle ctor");
}
}