Considerations
I have a couple of considerations for this architecture
Cards with Multiple Effects
Right now, you have a card that when played, draws two cards. In the future, you might want a card that draws 3 cards and then discards 1, or a card that discards 1 and then draws 3.
A good architecture will allow you to re-use code between cards with similar effects.
Cards which trigger other than when played
In a more complicated game, you might have a card that says, "When you draw this card, take two damage."
A good architecture will support weird cards like this.
Solution: Events
If you are working in C# (like with Unity), there is an elegant language feature that can help here called Events.
Each event can take an arbitrary number of subscribers, and fires all of them in order when those events are triggered.
Here is some example code.
public delegate void CardEffect(CardPlayer player, CardGameObject? target);
public class Card
{
public event CardEffect Played;
public event CardEffect Drawn;
public event CardEffect Discarded;
// TODO: Write some code here to invoke the events when they come up.
}
public static class ExampleCards
{
public static Card DrawTwo()
{
var card = new Card();
card.Played += ExampleCardEffects.Draw(2);
return card;
}
public static Card DrawThreeDiscardOne()
{
var card = new Card();
card.Played += ExampleCardEffects.Draw(3);
card.Played += ExampleCardEffects.Discard(1);
return card;
}
public static Card TakeDamageWhenDrawn()
{
var card = new Card();
card.Drawn += ExampleCardEffects.TakeDamage(2);
return card;
}
}
public static class ExampleCardEffects
{
public static CardEffect Draw(int amount)
{
return (player, target) => player.Draw(amount);
}
public static CardEffect Discard(int amount)
{
return (player, target) => player.Discard(amount);
}
public static CardEffect DealDamage(int amount)
{
return (player, target) => player.DealDamage(target, amount);
}
public static CardEffect TakeDamage(int amount)
{
return (player, target) => player.DealDamage(player, amount);
}
}
```