隔离仅由特定类实例化的类:最佳实践
本文关键字:最佳 实例化 隔离 | 更新日期: 2023-09-27 18:25:53
好的,我使用的是两层类:某种"管理器"类,任务是获取一个对象,链接所有附加到它的项,并将其返回给调用者,以及一个"数据"类,其任务是根据特定请求调用数据库。
下面是我工作的一个例子。这是一个"经理"类:
public class CardManager
{
private static readonly CardData mCardDAL = new CardData();
public List<CardDisplay> ListCardsToShow(int _pageNumber, string _queryString, string _rarity, string _type, string _color, out int _totalCount)
{
List<CardDisplay> listToReturn = mCardDAL.ListCardsToShow(_pageNumber, _queryString, _rarity, _type, _color, out _totalCount);
LinkListCardDisplayData(listToReturn);
return listToReturn;
}
/// <summary>
/// Method links the card set with each cards of the list.
/// </summary>
/// <param name="_listToReturn"></param>
private static void LinkListCardDisplayData(IEnumerable<CardDisplay> _listToReturn)
{
try
{
foreach (CardDisplay item in _listToReturn)
{
LinkCardDisplayData(item);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
private static void LinkCardDisplayData(CardDisplay _item)
{
_item.mMasterCardID = _item.mMasterCard.mCardID;
ImagesManager.GetCardImages(_item);
if (_item.mChildCard != null)
{
_item.mChildCardID = _item.mChildCard.mCardID;
}
}
}
这里有一个"数据"类,即本次事件中的CardData
类:
public class CardData
{
internal List<CardDisplay> ListCardsToShow(int _pageNumber, string _queryString, string _rarity, string _type, string _color, out int _totalCount)
{
using (DatabaseEntity db = new DatabaseEntity())
{
db.Database.Connection.Open();
List<CARD> cardData;
List<CardInfo> listCards;
if (!String.IsNullOrWhiteSpace(_queryString))
{
var predicate = GetCardPredicate(_queryString);
if (_rarity != "All")
{
predicate = predicate.And(_item => _item.CARD_RARTY == _rarity);
}
if (_color != "All")
{
predicate = predicate.And(
_item => _item.CARD_MANA_COST.Contains(_color) || _item.CARD_COLOR.Contains(_color));
}
if (_type != "All")
{
predicate = predicate.And(_item => _item.CARD_TYPE.Contains(_type));
}
var cardQry = from c in db.CARD.AsExpandable().Where(predicate)
select c;
_totalCount = cardQry.Count();
int pageCount = _pageNumber - 1;
cardData = cardQry.OrderBy(_x => _x.CARD_IDE).Skip(pageCount * 20).Take(20).ToList();
for (int i = 0; i < cardData.Count; i++)
{
CARD card = cardData[i];
if (cardData.Any(_item => _item.CARD_MASTER_IDE == card.CARD_IDE))
{
cardData.Remove(card);
}
}
listCards = DataConverter.ListCardDATAToListCardInfo(cardData);
}
else
{
// If we are here then the user browsed to get the 300 latest entries available.
Expression<Func<CARD, bool>> cardPredicate = PredicateBuilder.True<CARD>();
if (_rarity != "All")
{
cardPredicate = cardPredicate.And(_item => _item.CARD_RARTY == _rarity);
}
if (_type != "All")
{
cardPredicate = cardPredicate.And(_item => _item.CARD_TYPE.Contains(_type));
}
if (_color != "All")
{
cardPredicate =
cardPredicate.And(
_item => _item.CARD_MANA_COST.Contains(_color) || _item.CARD_COLOR.Contains(_color));
}
var cardQry = (from c in db.CARD.AsExpandable().Where(_item => !_item.CARD_NAME.Contains("(Foil)"))
select c).OrderByDescending(_x => _x.CARD_SET.CARD_SET_RELES_DATE).Take(300);
cardQry = cardQry.Where(cardPredicate);
_totalCount = cardQry.Count();
int pageCount = _pageNumber - 1;
cardData = cardQry.Skip(pageCount * 20).Take(20).ToList();
for (int i = 0; i < cardData.Count; i++)
{
CARD card = cardData[i];
if (cardData.Any(_item => _item.CARD_MASTER_IDE == card.CARD_IDE))
{
cardData.Remove(card);
}
}
listCards = DataConverter.ListCardDATAToListCardInfo(cardData);
}
List<CardDisplay> listToReturn = MakeListCardDisplay(listCards);
return listToReturn;
}
}
}
我的问题不是"如何"编写代码(但我喜欢学习,可以随意发表建设性的评论),而是它的结构。例如,我希望CardData
类由"管理器"类独占地实例化,这意味着我不能在控制器中创建public static readonly CardData mCardDAL = new CardData();
对象。
有没有一种方法可以隔离我的类,使任何人都"被迫"通过管理器来获取对象?我的工作方式很好,我的代码好吗?
可以通过使CardData
成为Manager
内部的嵌套类来拒绝外部访问,通过使其成为protected
来阻止其构造函数,并创建一个private
实例类:
public class Manager
{
public class Manager
{
CardData c = new CardDataInternal();
}
private class CardDataInternal : CardData
{
public CardDataInternal()
{ }
}
public class CardData
{
protected CardData()
{ }
}
}
您可以通过使manager类成为嵌套类,然后为Card
类提供一个私有构造函数(允许嵌套类调用)来保持这两个对象的公共性,类似于:
public class Card
{
private Card()
{
}
public class Manager
{
public Card Create()
{
return new Card();
}
}
}
因此,您可以自由创建new Card.Manager()
,但创建新Card
的唯一方法是通过Create()
方法。
使用接口的@Patrick方法的替代方案:
public interface ICardData { ... }
public class Manager
{
public class Manager()
{
CardData c = new CardData();
}
private class CardData : ICardData
{
public CardData() { }
}
}
通过在嵌套的私有类上使用接口而不是构造函数,您还可以使用mock实现进行单元测试。。。可能对CardData来说并不重要,但如果你在一个有有趣行为的类上这样做,那就非常重要了。
从提供的代码来看,您可能希望将CardData类放在CardManager类中,并将其设为私有类,以便只有CardManager才能访问它。
public class CardManager
{
private class CardData { ... }
}