3

例如说你有一个基础抽象类

public abstract Foo
{
  IFlyable _fly;
  ISwimmable _swim;

  void performSwim()
  {
    _swim.swim();
  }

 void performFly()
 {
   _fly.fly();
 }
}

并拥有系统中的行为/算法

interface IFlyable { void fly(); }
interface ISwimmable { void swim(); }
interface IVoteable { void vote(); }

等等等等

现在你有多个实现它的类,具体的 IFlyable、ISwimmable 等

class Bar: Foo { _swim = new ConcerteSwim(); }
class Baz: Foo { _fly = new ConcreteFly(); }

等等等等

一种是使用 Foo 基类中的策略模式来交换行为。

我们也可以使用装饰器模式将其包装为特定的行为,但由于装饰器使用基类包装它,如果稍后我们向对象添加更多行为,我们如何真正允许打开关闭原则在不触及基类的情况下工作。由于这些行为在我们添加更多时可能具有不同的签名,而不仅仅是例如调用装饰器

void performSwim()
{
     swimWithMoreSpeed() + foo.performSwim()
}

我想我的问题是如果我添加更多行为,我怎么能不修改基类并且仍然能够说添加 IWeaponBehavior、ISomeBehaviour 到一个类。

例如我想上课

public class XYF: Foo
{

}

但是我想给它一些 ISomeBehaviour 的行为,有没有办法可以说用这些行为包装它,或者更像是一个 ConcreteFoo 用这些行为包装它,现在做一些事情而不是在具体 xyz 上实现接口虽然这让你实现了这么多种具体的行为类,比如游泳行为、空行为等,但没有办法摆脱它。

有没有办法在设计模式中做到这一点?它几乎看起来像是一种混合模式。

我知道,如果它像鸭子一样走路,像鸭子一样嘎嘎叫,但需要电池,那么你的抽象就有问题了。

希望这是有道理的。

4

3 回答 3

4

试试装饰器模式。要支持新行为,您只需实现一个新类,该类继承自Foo、实现IWeaponBehavior和装饰另一个Foo对象。然后您现在可以将其WeaponDecorator用作FooorIWeaponBehavior并且仍然可以访问Foo它所装饰的基础。

基类:

public abstract Foo { void Jump(); }

具有基本行为的具体子类:

public Bar : Foo { void Jump() { /* jump! */ } }
public Baz : Foo { }

行为接口:

interface IFlyable { void Fly(); }
interface ISwimmable { void Swim(); }

具有行为的装饰器子类:

public FlyableFoo : Foo, IFlyable
{
    public Foo Base { get; set; }
    public FlyableFoo(Foo base) { Base = base; }
    void Fly() { Base.Jump(); /* fly! */ }
}

现在我们可以使用它的特定实现进行任何Foo飞行Jump()

Baz baz = new Baz();
FlyableFoo flybaz = new FlyableFoo(baz);
flybaz.Fly();
于 2009-02-12T21:48:17.413 回答
0

访客模式怎么样?它允许基类的实现者改变行为,而无需强制基类针对每个新实现进行更改:

public interface IFlyable { void fly(); }
public interface ISwimmable { void swim(); }
public interface IVoteable { void vote(); }

public abstract class Animal
{
    public abstract void Accept(AnimalVisiter Visitor);
    //some common behaviour is here
    public bool LegsKicking { get; set; }
    public bool ArmsFlapping { get; set; }
}

//This class now absorbs new responisbilities, so base class doesn't have to
public class AnimalVisiter
{
    public void Visit(ISwimmable Subject)
    {
        Subject.swim();
    }

    public void Visit(IVoteable Subject)
    {
        Subject.vote();
    }

    public void Visit(IFlyable Subject)
    {
        Subject.fly();
    }
}

public class SwimmingHuman : Animal, ISwimmable
{
    public void swim()
    {
        LegsKicking = true;
    }

    public override void Accept(AnimalVisiter Visitor)
    {
        Visitor.Visit(this);
    }
}

public class VotingHuman : Animal, IVoteable
{

    public override void Accept(AnimalVisiter Visitor)
    {
        Visitor.Visit(this);
    }

    public void vote()
    {
        VoteCast = true;
    }
    //some specific behaviour goes here
    public bool VoteCast { get; set; }
}

public class SwimmingTiger : Animal, ISwimmable
{

    public void swim()
    {
        LegsKicking = true;
        //also wag tail, flap ears
    }

    public override void Accept(AnimalVisiter Visitor)
    {
        Visitor.Visit(this);
    }
}
于 2009-02-16T22:43:01.263 回答
-2

所以这是我对此的看法:

public enum ActionType
{
   Swim, Vote, Fly
};

public interface IBehavior
{
   public boolean ActionReady;
   public ActionType _type;

   public void performMyAction();
}

public abstract Foo
{
  IBevahior[] behaviors;

  // if you want to keep track of behavior states as on or off
  void perform()
  {
    for(int i = 0; i< behaviors.length; i++)
    {
       if(behaviors[i].ActionReady)
       {
          behaviors[i].performMyAction();
       }
    }
  }

  // if you want to call behaviors individually
  void performType(ActionType type)  // however you want to make the distinction
  {
     for(int i = 0; i < behaviors.length; i++)
     {
        if(behaviors[i].type = type)
        {
            behaviors[i].performMyAction();
        }
     }
  }
}

然后让您的接口(如 ISwimmable 等)从 IBehavior 继承。

于 2009-02-12T21:39:53.520 回答