比如说你有一个基础抽象类
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基类中的策略模式来交换行为。
我们也可以使用装饰器模式用某种行为来包装它,但是由于装饰器用基类包装它,如果我们以后添加更多行为,我们如何实际允许open close原则工作而不触及基类对象。由于这些行为可能会有不同的签名,因为我们添加更多,而不仅仅是例如调用装饰器
void performSwim()
{
swimWithMoreSpeed() + foo.performSwim()
}
我想我的问题是,如果我添加更多行为,我怎么能不修改基类,仍然可以说将IWeaponBehavior,ISomeBehaviour添加到类中。
例如我想要一个班级
public class XYF: Foo
{
}
但是我想给它一些ISomeBehaviour的行为,有没有办法可以用这些行为来包装它,或者更像是这里是一个ConcreteFoo用这些行为包装它现在做的东西而不是实现接口在具体的xyz上,虽然这会让你实现如swimbehaviour,nullbehaviour等许多类型的具体行为,但是没有办法摆脱它。
有没有办法在设计模式中这样做?它几乎看起来像模式的混合。
我知道,如果它像鸭子一样行走,像鸭子一样呱呱叫,但需要电池,那么抽象就有问题。
希望这是有道理的。
答案 0 :(得分:3)
尝试装饰器模式。要支持新行为,您只需实现一个继承自Foo
,实现IWeaponBehavior
并装饰另一个Foo
对象的新类。然后,您现在可以将WeaponDecorator
用作Foo
或IWeaponBehavior
,并仍然可以访问其装饰的基础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();
答案 1 :(得分: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);
}
}
答案 2 :(得分:-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。