为了账号安全,请及时绑定邮箱和手机立即绑定

c#中继承相同接口得到的相似代码有没有好的解耦方法?

c#中继承相同接口得到的相似代码有没有好的解耦方法?

C#
catspeake 2023-04-29 16:37:23
比方说,在代码中,我们有一个 IEnemy 接口,它有一个名为 Attack() 的方法。假设我们有五个派生自 IEnemy 接口的敌人。在其中三个类中,我们使用完全相同的 Attack 方法实现。在其中一个中,我们也使用相同的代码,但在方法的某处更改了一两行代码。而且,在上一节课中,我们仍然有相同的实现,但在方法的某处添加/删除了一两行代码。您对解耦这段代码有什么建议吗?如果我们在方法中间更改某些内容,我已经尝试覆盖不起作用的方法。我尝试使用委托作为参数,当我们想要更改方法中其他地方的某些内容时,它不起作用。我尝试使用接口的扩展方法来创建默认实现,但其中两个类仍然具有解耦代码。interface IEnemy{    void Attack();}class Enemy1 : IEnemy{    public void Attack()    {        Console.WriteLine("This is an enemy");        Console.WriteLine("Enemy is jumping");        Console.WriteLine("Enemy is attacking");    }}class Enemy2 : IEnemy{    public void Attack()    {        Console.WriteLine("This is an enemy");        Console.WriteLine("Enemy is jumping");        Console.WriteLine("Enemy is attacking");    }}class Enemy3 : IEnemy{    public void Attack()    {        Console.WriteLine("This is an enemy");        Console.WriteLine("Enemy is jumping");        Console.WriteLine("Enemy is attacking");    }}//Let's say this enemy is not capable of jumping, so we want to remove the code that says enemy is jumping.class Enemy4 : IEnemy{    public void Attack()    {        Console.WriteLine("This is an enemy");        Console.WriteLine("Enemy is attacking");    }}//Let's say this is the boss and instead of jumping, it will roar.//So we want to change the code that says enemy is jumping to enemy is roaring.class Enemy5 : IEnemy{    public void Attack()    {        Console.WriteLine("This is an enemy");        Console.WriteLine("Enemy is roaring");        Console.WriteLine("Enemy is attacking");    }}
查看完整描述

2 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

我会将接口替换为具有默认实现的抽象基类,然后将Attack方法分解为单独的可重写步骤。我Attack为完全拥有自己的攻击模式的敌人制作了虚拟。


abstract class BaseEnemy {

    public virtual void Attack() {

        AttackIdentify();

        AttackSignal();

        AttackAttack();

    }


    protected virtual void AttackIdentify() {

        Console.WriteLine("This is an enemy");

    }


    protected virtual void AttackSignal() {

        Console.WriteLine("Enemy is jumping");

    }


    protected virtual void AttackAttack() {

        Console.WriteLine("Enemy is attacking");

    }

}


class Enemy1 : BaseEnemy {

    protected override void AttackIdentify() {

        Console.WriteLine("This is an enemy 1");

    }

}


class Enemy2 : BaseEnemy {

}


class Enemy3 : BaseEnemy {

    protected override void AttackIdentify() {

        Console.WriteLine("This is an enemy 3");

    }

}


//Let's say this enemy is not capable of jumping, so we want to remove the code that says enemy is jumping.

class Enemy4 : BaseEnemy {

    protected override void AttackSignal() { }

}


//Let's say this is the boss and instead of jumping, it will roar.

//So we want to change the code that says enemy is jumping to enemy is roaring.

class Enemy5 : BaseEnemy {

    protected override void AttackSignal() {

        Console.WriteLine("Enemy is roaring");

    }

}

如果您仍然需要该接口IEnemy,则可以BaseEnemy实现它。


查看完整回答
反对 回复 2023-04-29
?
HUWWW

TA贡献1874条经验 获得超12个赞

这是它的抽象类版本的基本示例。


public abstract class Enemy

{

    public bool CanJump { get; set; } = false;

    public bool CanRoar { get; set; } = false;

    public bool CanAttack { get; set; } = false;


    public virtual void Attack()

    {

        Console.WriteLine("This is an enemy");


        if (CanJump)

        {

            Console.WriteLine("Enemy is jumping");

        }


        if (CanRoar)

        {

            Console.WriteLine("Enemy is roaring");

        }


        if (CanAttack)

        {

            Console.WriteLine("Enemy is attacking");

        }

    }

}


public class Enemy1 : Enemy

{

    public Enemy1()

    {

        CanJump = true;

        CanRoar = true;

    }

}


public class Enemy2 : Enemy

{

    public Enemy2()

    {

        CanRoar = true;

        CanAttack = true;

    }

}


public class Enemy3 : Enemy

{

    public Enemy3()

    {

        CanRoar = true;

        CanAttack = true;

    }


    public override void Attack()

    {

        base.Attack();


        Console.WriteLine("Custom thing");

    }

}

您会注意到并Enemy1以Enemy2相同的方式工作,但设置不同的属性,当您调用该Attack方法时,这些属性将相应显示。我希望您注意的有趣部分是Enemy3覆盖该方法的类。Virtual这可以通过在抽象类中创建方法来实现Enemy。


此覆盖允许仍然调用Attack类中的基类方法Enemy,而且它还显示自定义值。所以它非常灵活。


请注意,这对于提供的示例非常有效,但是通过使用您的类名,我可以轻松地假设真正的项目是什么,这不是正确的方法。您不应该为每个敌人创建一个不同的类,但这超出了问题的范围。


查看完整回答
反对 回复 2023-04-29
  • 2 回答
  • 0 关注
  • 120 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信