Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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
Oop 重构包含半相关和半不相关函数的两个类时使用哪种设计模式?_Oop_Design Patterns - Fatal编程技术网

Oop 重构包含半相关和半不相关函数的两个类时使用哪种设计模式?

Oop 重构包含半相关和半不相关函数的两个类时使用哪种设计模式?,oop,design-patterns,Oop,Design Patterns,我有两个物体,鸟和狗Bird和Dog对大约50%的方法/属性有相同的实现,但对其他50%的方法/属性有不同的不相关的方法和属性 我正在重构,我不知道什么是最好的策略 我尝试定义一个超类Animal来实现超类中的常用方法,并让子类定义自己的方法/属性 我写了一个工厂,返回一个或另一个-这一切似乎都是正确的。。。但是我在编写调用代码时感到困惑。。e、 g public class Animal{ public string Talk(){ return "yak yak yak"; } pub

我有两个物体,鸟和BirdDog对大约50%的方法/属性有相同的实现,但对其他50%的方法/属性有不同的不相关的方法和属性

我正在重构,我不知道什么是最好的策略

我尝试定义一个超类Animal来实现超类中的常用方法,并让子类定义自己的方法/属性

我写了一个工厂,返回一个或另一个-这一切似乎都是正确的。。。但是我在编写调用代码时感到困惑。。e、 g

public class Animal{
   public string Talk(){ return "yak yak yak";
}
public class Dog:Animal{
   public string Walk(){ return "walk walk walk"; }
}
public class Bird:Animal{
   public string Fly(){ return "flap flap flap"; }
}
...
Animal thing = CreatureFactory.GetCreature(modifier);
当我想用东西说话
没有问题

Debug.Print(thing.Talk());

但是,作为程序员,当我知道我想要它飞行时,我会把它投给鸟吗?这似乎是错误的。。。但是在上定义的方法也似乎是错误的。

你要么把它扔给鸟:

Debug.Print(((Bird)thing).Fly());
或者你一直把它当作一只鸟:

// depending on how the factory works, might not need the cast
Bird thing = (Bird) CreatureFactory.GetCreature(modifier);
Debug.Print(bird.Fly());
我想说: 如果你的狗也有一个方法,使“运动”的想法,我会改变名称的飞行和步行“移动”,然后叫它。
如果你的狗没有类似的东西,开发人员就不能在任何对象上调用它,因为不是所有动物都能飞:)

首先,我会在名为
Move()
的基类上放置一个虚拟方法,并在派生类中重写它

(以下是C#)

但要回答您的问题,如果您希望动物在(且仅在)它能飞的情况下移动,您可以定义一个
IFlyingAnimal
接口,并使用
Bird
实现它。然后,您可以测试
动物是否实现了该接口。如果是,则将其强制转换为
iflynganimal
,并调用其
Fly()
方法

public interface IFlyingAnimal {
   string Fly();
}
public class Bird : Animal, IFlyingAnimal {
   public string Fly(){ return "flap flap flap"; }
}

//later, in your main program
public string FlyIfYouCan(Animal animal) {
    if (animal is IFlyingAnimal)
        return ((IFlyingAnimal)animal).Fly();

    return "I can't fly!";
}

您不必使用接口;如果(动物是鸟),您可以使用
。但这样做是更好的练习;鸟类不是唯一会飞的动物,所以你的决定是基于你的物品的功能,而不是它是什么。这就是接口的用途。

我的方法是让工厂方法返回具体类型,而不是超类。您仍然可以将它传递给可以在超类上操作的方法,但是您在需要时可以使用具体类的一项,而不需要强制转换它

Bird bird = CreatureFactory.GetBird();

现在,您仍然可以将它们用作
动物

public class Trainer
{
     public void TeachToSpeak( Animal animal )
     {
          ...
          animal.Talk();
     }
}

但是,由于它们被输入到具体的类中,您可以适当地使用它们不共享的方法。

举个例子,当您希望您的
动物
飞行时,执行飞行的类与错误的类一起工作——它应该使用
本身或一些
ICanFly
接口


虽然其他答案说您可以通过强制转换来实现,但代码的可读性将因此受到影响。当工厂创建对象时,绝对没有理由将这些对象强制转换为其他类型。还有一个确凿的证据表明,当您开始强制转换到其他类型时,您的类违反了单一责任原则

这个想法不错,只是很多鸟也会走路。@MattBall:所以提供一个三维矢量和一个三维网格。现在你可以检查它是否在飞。如果你想让它飞,为什么不把它声明为鸟呢?想想这个:你怎么知道你有一只鸟?为什么要让它飞行()。可能是因为某些输入满足了某些条件,对吗?您的动物需要
DoSomethingWith(输入)
。鸟和狗应该按他们认为合适的方式执行。谢谢所有回答的人。
Dog dog = CreatureFactory.GetDog();
public class Trainer
{
     public void TeachToSpeak( Animal animal )
     {
          ...
          animal.Talk();
     }
}