我按照以下方式对编码系统进行编码:
成就 - 所有成就必须实现的界面
AchievementManager - 具有用户ID的类检查所有成就
我的想法是在ArchivementManager上有一个共享功能,因为我可以执行类似
的操作AchievementManager.checkUser(userId)
或
AchievementManager.check(userId, achievementId)
无论如何,AchivementManager应该为每个IAchievement实现调用函数检查。
因为我正在检查每个成就的实例没有任何意义我希望能够将检查方法声明为共享/静态。所以在AchievementManager中我可以调用
AchivementXXX.check(userId)
但我无法在界面中声明共享功能。
有没有解决方法?实施一个成就系统是一个不好的方法吗?
编辑:
这不是游戏,而是ASP.NET中的网站
答案 0 :(得分:1)
如果您的方法是定义一个接口,那么是的,让AchievementManager保存每个相关成就类型的实例是有意义的。
这也是有道理的,因为人们会期望成就实例需要存在,例如为了跟踪各种游戏状态并收听各种游戏事件,以便他们能够检测到已经实现了成就。否则,成就将如何实现其Check方法?
答案 1 :(得分:0)
您可以在Superclass Achievement中实现您的接口,然后将该类声明为MustInherit。因此,每个成就都继承自超类并且可以覆盖独特的部分。 你的check方法可以设置为nonoverridable,这样任何人都无法修改它
答案 2 :(得分:0)
所以继续评论,你有一些选择..
public class AchievementA : AchievementBase
{
public void GetAchievementForAByUser(int userId)
{
base.CheckId(userId);
}
}
public class AchievementB : AchievementBase
{
}
public class AchievementManager : IAchievement
{
protected void CheckId(int userId)
{
}
}
您的界面IAchievement将实施一个方法合同,这些方法可用于每个成就子类。
答案 3 :(得分:0)
还有一种不使用接口和继承的方法:
class Achievement {
private Predicate<UserId> actualCheckUser;
public bool CheckUser(UserID userId) {
return actualCheckUser(userId);
}
public Achievement(Predicate<UserId> checkUser) {
if (checkUser == null) {
throw new ArgumentNullException("checkUser");
}
actualCheckUser = checkUser;
}
}
您调用achievement的方法来检查用户是否拥有它。如果您将成就表示为类型,则achievement的方法是类型的方法,换句话说,是静态方法。但是你不能在接口中使用静态方法。如果您将成就表示为 objects ,那么achievement的方法是一个普通的旧对象的方法。
但是你必须使这个方法在Achievement类的不同实例中表现不同。实现此目的的一种方法实际上是使CheckUser
抽象并覆盖它,但是您再次需要为每个成就声明一个单独的类。另一种方法是使用委托 - 你将它插入你的成就对象,就是这样。在引擎盖下,它也会导致创建一个额外的类。
就我个人而言,我不知道哪种设计更好,但我认为就类型而言,元编程在对象方面比OOP更难。
答案 4 :(得分:0)
我知道这篇文章差不多有一年了,但为什么不使用DI呢?例如:
interface IAchievement {
void Check(User user);
}
class UserMade200PostsAchievement : IAchievement {
void Apply(User user) {
var postCount = _repo.AsQueryable<Post>().Count(x => x.CreatedByUserId == user.Id);
if (postCount >= 200)
//apply achievement, insert some data, whatever
}
}
全部注册:
//Note this may not be the exact command, depends on your choice of IoC container
container.RegisterInterfaceImplementers(typeof(IAchievement));
public class AchievementManager {
//All instances of IAchievement injected
private IAchievement[] Achievements
public AchivementManager(IAchievement[] achievements) {
Achievements = achievements;
}
public void Check(User user) {
foreach(var a in achivements)
a.Apply(user);
}
}
这样,当您添加新的成就时,它会自动被拾取。