我正在学习泛型/使用依赖注入/接口以便松散耦合类 - 但是,我正在努力。
对于以下简单的卡/卡片示例,我怎样才能最好地调整这些类(使用上述技术),以便我可以传递任何类型的“卡/ ICard”列表,以便能够填充/打印Deck说的类型。因此,例如,在Main中,我希望能够传入List或List,并且对于deck来说能够处理这种方式。
Deck.cs
public class Deck
{
List<Card> cards;
public Deck(List<Card> cards)
{
this.cards = cards;
foreach (Card.Suit suit in Enum.GetValues(typeof(Card.Suit))) {
foreach (Card.Val value in Enum.GetValues(typeof(Card.Val))) {
cards.Add(new Card(suit, value));
}
}
}
public void printDeck()
{
foreach(Card x in cards)
{
Console.WriteLine(x.ToString());
}
}
}
}
Card.cs
public class Card : ICard {
Suit suit;
Val value;
public Card(Suit suit, Val value)
{
this.suit = suit;
this.value = value;
}
public override string ToString()
{
string formatCard = "Suit: " + suit + " Value: " + value;
return formatCard;
}
public enum Suit
{
HEARTS = 1,
SPADES = 2,
CLUBS = 3,
DIAMONDS = 4
}
public enum Val
{
ONE = 1,
TWO = 2,
THREE = 3,
FOUR = 4,
FIVE = 5
}
}
}
SpecialCard.cs
public class SpecialCard : ICard{
Suit suit;
Val val;
public SpecialCard(Suit suit, Val val)
{
this.suit = suit;
this.val = val;
}
public override string ToString()
{
string formatCard = "Dragon: " + suit + " Value: " + val;
return formatCard;
}
public enum Suit
{
RIDGEBACK = 1,
FIREBALL = 2,
SHORTSNOUT = 3,
HORNTAIL = 4
}
public enum Val
{
UNO = 1,
DOS = 2,
TRES = 3,
QUATTRO = 4,
CINCZ = 5
}
}
}
ICard.cs
public interface ICard
{
string ToString();
}
主要
static void Main()
{
Deck deck = new Deck(new List<Card>());
deck.printDeck();
Console.ReadKey();
}
感谢您的任何指示! FYP
答案 0 :(得分:1)
我不会把这个套装和价值作为枚举,因为它很难替代不同的实现。一般来说,我会从提供逻辑的类中分离出持有卡片或卡片等状态的类,例如卡片生成器。
我认为你在ICard中不需要ToString(),因为所有类都继承System.Object,它实现了ToString()。无论如何,我不认为卡应该知道它自己的长描述。为什么不让客户根据可用的信息(适合,价值)来决定。
鉴于两种类型的卡的实现是相同的,我只有一个逻辑非常少的类。套装和价值现在可以只是一个字符串,因为您所做的只是打印值。如果您需要稍后比较卡的强度,您可能希望将Value更改为具有int值和字符串描述的类。
public class Card
{
public string Suit { get; set; }
public string Value { get; set; }
}
然后,您的套牌将成为卡片清单和所用套装的类型,并将其自身的建筑物委托给其他地方,以避免违反关注点。
public class Deck
{
public IEnumerable<Card> Cards { get; set; }
public string SuitName { get; set; }
}
然后你的大部分逻辑将存在于甲板构建器中。为了使客户能够知道要构建哪个套牌,我将创建一个枚举。
public enum DeckType
{
Standard,
Special
}
并且构建器将是(静态,因为它没有状态)
public static class DeckBuilder
{
public Deck Build(DeckType deckType)
{
var deck = new Deck();
switch (deckType)
{
case DeckType.Standard:
deck.SuitName = "Suit";
deck.Cards = CreateStandardCards();
break;
case DeckType.Special:
deck.SuitName = "Dragon";
deck.Cards = CreateSpecialCards();
break;
default:
throw new ArgumentException("deckType");
}
}
private IEnumerable<Card> CreateStandardCards()
{
var suits = new List<string> { "Hearts", "Clubs", "Diamonds", "Spades" };
var values = new List<string> { "One", "Two", "Three", "Four", "Five" };
return CreateCards(suits, values);
}
private IEnumerable<Card> CreateSpecialCards()
{
var suits = new List<string> { "Ridgeback", "Fireball", "Shortsnout", "Horntail" };
var values = new List<string> { "Uno", "Dos", "Tres", "Quattro", "Cincz" };
return CreateCards(suits, values);
}
private IEnumerable<Card> CreateCards(IEnumerable<string> suits, IEnumerable<string> values)
{
foreach (var suit in suits)
foreach (var value in values)
yield return new Card { Suit = suit, Value = value };
}
}
这种方法的替代方法是创建一个IDeckBuilder,它具有StandardDeckBuilder和SpecialDeckBuilder的不同实现,这意味着不需要枚举。如果switch语句变大(例如,如果添加了更多依赖于deck类型的属性),我会这样做。
客户端需要调用相应的构建器。我也会在这里移动printDeck逻辑。甲板类不应该知道如何打印。它不应该知道输出进入控制台。
static void Main()
{
var deck = DeckBuilder.Build(DeckType.Standard);
foreach (var card in deck.Cards)
Console.WriteLine(deck.SuitName + ": " + card.Suit + " Value: " + card.Value);
Console.ReadKey();
}
我没有尝试过,所以可能无法编译 - 这是我将使用的整体设计的例证。