Decorator Bindings
另外Zenject的特性功能是可以使用装饰模式来设计绑定;允许你更简单的实现装饰模式
Example
作为一个示例,让我们说一个类包含了统计指定敌人在我们的游戏里面,我们有两个敌人(兽人和恶魔):
public interface IEnemyStats
{
float Damage
{
get;
}
float Health
{
get;
}
}
public class OrcStats : IEnemyStats
{
public float Damage
{
get {
return 1; }
}
public float Health
{
get {
return 50; }
}
}
public class DemonStats : IEnemyStats
{
public float Damage
{
get {
return 7; }
}
public float Health
{
get {
return 20; }
}
}
public class TestInstaller : MonoInstaller<TestInstaller>
{
public override void InstallBindings()
{
Container.Bind<IEnemyStats>().To<OrcStats>().AsSingle();
}
}
一种说法是我们偶尔想升级随机单位到添加一些变化到游戏;我们可以使用装饰:
public class WeaponUpgradeEnemyDecorator : IEnemyStats
{
readonly IEnemyStats _stats;
public WeaponUpgradeEnemyDecorator(IEnemyStats stats)
{
_stats = stats;
}
public float Damage
{
get {
return _stats.Damage + 2; }
}
public float Health
{
get {
return _stats.Health; }
}
}
public class TestInstaller : MonoInstaller<TestInstaller>
{
public override void InstallBindings()
{
Container.Bind<IEnemyStats>().To<OrcStats>().AsSingle();
Container.Decorate<IEnemyStats>().With<WeaponUpgradeEnemyDecorator>();
}
}
通过使用Container.Decorate像我这里做,任何使用代码可以继续使用IEnemyStats
跟之前一样,
但升级到引起更多伤害;这个升级也可以应用到任何IEnemyStats派生类,同样也可以兽人或恶魔;
我们把装饰链接在一起,因此如果想要应用不同的升级生命值,我们可以同时达到:
public class ShieldUpgradeEnemyDecorator : IEnemyStats
{
readonly IEnemyStats _stats;
public ShieldUpgradeEnemyDecorator(IEnemyStats stats)
{
_stats = stats;
}
public float Damage
{
get {
return _stats.Damage; }
}
public float Health
{
get {
return _stats.Health + 20; }
}
}
public class TestInstaller : MonoInstaller<TestInstaller>
{
public override void InstallBindings()
{
Container.Bind<IEnemyStats>().To<OrcStats>().AsSingle();
Container.Decorate<IEnemyStats>().With<WeaponUpgradeEnemyDecorator>();
Container.Decorate<IEnemyStats>().With<ShieldUpgradeEnemyDecorator>();
}
}
因此现在我们的兽人统计将获得伤害和生命值的提升;
注意:排序我们应用的装饰在这个例子里面没有关系,但在其他情况下有需要;装饰将会应用到其他已经添加了的,
这个例子里面,应该看起来这样:
ShieldUpgradeEnemyDecorator(WeaponUpgradeEnemyDecorator(OrcStats()))
其他简单的方式使用装饰应该想象添加额外的日志,或验证输出值,或概要分析已经存在的接口,类如:
public interface ISaveGameHandler
{
void SaveGame();
}
public class SaveGameHandler : ISaveGameHandler
{
public void SaveGame()
{
// Some long running operation
}
}
public class SaveGameProfilerDecorator : ISaveGameHandler
{
readonly ISaveGameHandler _handler;
public SaveGameProfilerDecorator(ISaveGameHandler handler)
{
_handler = handler;
}
public void SaveGame()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
_handler.SaveGame();
stopwatch.Stop();
Debug.Log(string.format("Took {0:0.00} seconds to save the game!", stopwatch.Elapsed.TotalSeconds));
}
}
public void InstallBindings()
{
Container.Bind<ISaveGameHandler>().To<SaveGameHandler>().AsSingle();
Container.Decorate<