Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 原型模式,为什么我需要一个接口?_C#_Design Patterns_Interface_Prototype Pattern - Fatal编程技术网

C# 原型模式,为什么我需要一个接口?

C# 原型模式,为什么我需要一个接口?,c#,design-patterns,interface,prototype-pattern,C#,Design Patterns,Interface,Prototype Pattern,我正在玩弄设计模式,目前我正在使用原型模式。这个模式让我想知道,为什么我需要这个模式的接口,没有接口我不能实现同样的功能吗 我已经创建了两个示例,有人能解释我为什么需要这个接口吗 接口示例: 这是我的接口类: interface IWeapon { IWeapon Clone(); } 我的具体课程: class Rifle : IWeapon { public IWeapon Clone() { return (IWeapon)this.Member

我正在玩弄设计模式,目前我正在使用原型模式。这个模式让我想知道,为什么我需要这个模式的接口,没有接口我不能实现同样的功能吗

我已经创建了两个示例,有人能解释我为什么需要这个接口吗

接口示例:

这是我的接口类:

interface IWeapon
{
    IWeapon Clone();
}
我的具体课程:

class Rifle : IWeapon
{

    public IWeapon Clone()
    {
        return (IWeapon)this.MemberwiseClone();
    }

}
克隆过程

 //Create rifle
 Rifle rifle = new Rifle();
 rifle.Name = "M4A1";
 rifle.Rounds = 30;

 //Copy Rifle
 Rifle rifleCopy = (Rifle)rifle.Clone();
这就是我在没有接口的情况下克隆的方式

public Rifle Clone()
{
   return (Rifle)this.MemberwiseClone();
}

有人能给我解释一下使用带接口的实现比不带接口的实现的优点吗?

接口的要点是为类定义一个通用的、可执行的结构

这些优点在您的示例中并不明显,因为您只声明了一种类型的
IWeapon
。真正的优势在于你开始创造不同的武器

IWeapon
类用于定义您对每种武器的期望,这样,您创建的每种继承自
IWeapon
的武器类都必须遵循这一点

归根结底,它是可以预测的,就你所期望的方法而言。然而,这些方法所做的事情对于每种武器来说都是独一无二的

例如:

interface IWeapon
{
    IWeapon Clone();
    Boolean HasAmmo();
    Int32 RoundInMagazine();
    Double GetCaliber();
    Fire();
    //etc.
}

//1st weapon
public class Shotgun : IWeapon
{
    private Int32 _ammo = 5;

    public void Clone()
    {
        return (IWeapon)this.MemberwiseClone();
    }

    public Boolean HasAmmo()
    {
        return _ammo > 0;
    }

    public Int32 RoundsInMagazine()
    {
        return _ammo;
    }

    public Double GetCaliber()
    {
        return 12.0;
    }

    public void Fire()
    {
        MessageBox.Show("bang!");
    }
}

//1st weapon
public class Rifle : IWeapon
{
    private Int32 _ammo = 30;

    public void Clone()
    {
        return (IWeapon)this.MemberwiseClone();
    }

    public Boolean HasAmmo()
    {
        return _ammo > 0;
    }

    public Int32 RoundsInMagazine()
    {
        return _ammo;
    }

    public Double GetCaliber()
    {
        return 5.56;
    }

    public void Fire()
    {
        MessageBox.Show("bang! bang! bang!");
    }
}
有了它,我可以定义任意数量的武器,每种武器都能为我提供最低的类内容。真正的优势在于,每个人都以自己独特的方式实现这些方法


想象一个接口,比如一组相关类的模板。

假设您有一个方法:

public void CloneAndShoot(IWeapon weapon) {
    IWeapon cloned = weapon.clone();
    cloned.shoot();
}
现在,如果您的接口定义如下:

interface IWeapon {
    IWeapon clone();
    void shoot();
}
你的方法可以毫无顾忌地接受各种武器:

CloneAndShoot(new M16());
CloneAndShoot(new M4A4());

可以
避免客户端应用程序中对象创建者的子类,就像抽象工厂模式一样。


当您有做相同事情的类,但使用不同的方法来实现时,接口非常好

用你的例子,假设我们有这样的东西

public interface ILongRangeWeapon
{
    void Fire();
}
现在,假设你有这些课程

public class Rifle : ILongRangeWeapon
{
    public void Fire()
    {
        // Pull the trigger
    }
}

public class NuclearMissile : ILongRangeWeapon
{
    public void Fire()
    {
        // Press the red button
    }
}
现在您可以在代码中使用iLongRangeAnswarm,它使用哪种机制发射并不重要,它只知道它可以发射

更实际的应用是连接到互联网。有多种连接方式,调制解调器、lan、wifi等。但是,您甚至不关心实例如何连接,您只想让它连接


有一些纯粹主义者说,你应该让一切都成为一个接口。我认为它增加了不需要的复杂性,只是为了增加复杂性。作为开发人员,您可以决定是否应该使用接口。

原型模式中的接口应该更像这样:

interface ICloneable
{
    ICloneable Clone();
}

也就是说,你不使用接口将你的类标记为武器,您可以使用它来标记它有一个
克隆
方法,可以用来创建副本。

您还可以在测试和能够在测试中使用IWeapon,而不需要为步枪和手枪设置相同的测试时添加这些改进。其中一些可能是属性。只是一个补充说明。@Magus在接口中没有属性。@DonBoitnott:事实上,你可以这样做。属性毕竟是方法。只是一些特殊的。你有一个关于复杂性的观点。我很少创建自己的接口,但当我需要它们时,它们是无价的。为任何东西创建接口都需要某种类型的设计。如果组件化的很好,那么制作组件的接口就可以提供适应性强、可测试的代码库。但这必须做好。即使这样,您仍然可能不需要所有的东西来拥有一个接口,但是当使用这种方法进行设计时,您可能会得到很多接口。