框架挑战*1 继承树改装饰模式(Decorator)

本文探讨了装饰模式在游戏开发中的应用,特别是如何利用该模式动态地为对象添加职责,以实现更灵活的对象功能扩展。对比了装饰模式与建造者模式、组合模式的区别,并讨论了在游戏开发中如何选择合适的设计模式。

装饰模式:

动态地给一个对象添加一些额外的职责,就扩展功能而言,该模式比生成子类方式更为灵活。

如果我按照继承树的方式来处理,那我生成一个实体【石榴树】,类与类之间的结构会帮我把所有内容处理好。但我如果要更改其中一个步骤,比如创造一种石榴树,保留其他特性,但不能存在!(好吧,非常抽象,大概理解为,这个石榴树是非存在物,是一种灵体),那我就要重新做一个这样的区别。
如果我用装饰器的方法,我可以一层一层去包裹这个石榴树,最后建成它。比如【石榴树!【树【植物【生物【物体【存在】】】】】】

这两个之间有什么区别吗?继承树中的问题可以用建造者模式来消除嘛?

我决定试一下用装饰器来处理这个石榴树的情况。这似乎意味着,任何一个半吊子,比如【物体【存在】】,也可以作为实体存在了。这就是与建造者模式的差异之一。但也只是方便与否的关系。

不,不仅仅是方便与否的关系,因为如果作为实体存在,就最好能够满足一些功能……

因为考虑到实际需求,我们的石榴树向前会变成*【预支付的】石榴树*,向后会变成*石榴树【植物】……但是前缀就是石榴树会遇到的情况,后缀就是石榴树当前的某种属性状态?

这样只涉及石榴树的属性?抑或可以用在非属性的任何地方,比如建造中。

先复习一下装饰模式-《设计模式与游戏完美开发》

public abstract class IShape
{
	//注意,有一个属性。似乎就是用来作为那个根基的存在(一个product)。
	protected RenderEngine m_RenderEngine=null;
	//子类则是需要可以获得这个存在。
	public void SetRenderEngine(RenderEngine theRenderEngine)
	{
		m_RenderEngine=theRenderEngine;
	}
	public abstract void Draw();
	public abstract string GetPolygon();
}


//继承这个接口的内容
public class Sphere :IShape
{	
	public override void Draw()
	{
		m_RenderEngine.Render("画个球")
	}	
	public override string GetPolygon()
	{
		return "Sphere多边形"
	}
}

在以上内容可以了解到,接口就像是一个共用的工具。当类里面有共用的承诺的时候,由这个父类接口来兑现!

而下面这个子类,就不是一个图形类了。它是为了扩展ishape的功能而存在的。我们看看它要怎么做到这一点。

public abstract class IShapeDecorator :IShape
{
	IShape m_Component;
	//构造这个类的时候,就需要获得一个组件。这种组件符合ISHAPE的接口。为了满足接口的功能,它支持调用了ISHAPE的内容,那这样是没有任何变化的。
	public IShapeDecorator(IShape theComponent)
	{
		m_Component =theComponent;
	}
	public override void Draw()
	{
		m_Component.Draw();
	}
	public override string GetPolygon()
	{
		return m_Component.GetPolygon();
	}
}

这个子类并不满足ishape的所有方法。它就像是包裹了shape的外面一层。任何其他物体需要通过这个外部的一层获得到内部的东西。

public abstract class IAdditional
{
	//神奇,它也有和Ishapey相似的内容。
	RenderEngine m_RenderEngine =null;
	public void SetRenderEngine(RenderEngine theRenderEngine)
	{
		m_RenderEngine =theRenderEngine;
	}
	//这就是有意义的那个功能
	public abstract void DrawOnShape(IShape theShape);
}

//第一个真正有用的类,外框,一个功能而已
public class Border :IAdditional
{
	public override void DrawOnShape(IShape theShape)
	{
		m_RenderEngine.Render("draw Border on "+theShape.GetPoly());
	}
}

public class BorderDecorator:IShapeDecorator
{
	Border m_Border =new Border();
	public BorderDecorator(IShape theComponent) :base(theComponent){}
	public virtual void SetRenderEngine(RenderEngine theRenderEngine)
	{
		base.SetRenderEngine(theRenderEngine);
		//因为这个画外框的功能也需要这个engine,所以给它
		m_Border.SetRenderEngine(theRenderEngine);
	}
	public override void Draw()
	{
		base.Draw();
		m_Border.DrawOnShape(this);
	}
}
//测试
sphere theSphere =new Sphere();
theSphere.SetRenderEngine(theOpenGL);
BorderDecorator =theShereWithBorder =new BorderDecorator(theShere);
theSphereWithBorder.SetRenderEngine(OPGL);
theSphereWithBorder.Draw();

我们看测试里,我们先构建了我们要画的一个组件,它是继承于一个抽象的类别的。
在我自己的需求里,我希望的是这个抽象是product_ab,而我们的一个内容,比如存在,就是继承这个抽象product_ab的product,例如通过如下结果来处理一个树:

Product myproduct =new Product();
myproduct.set_creator(productBuilder);

ExistDecorator existdeco =new ExistDecorator(myproduct);
existdeco.set_creator(existBuilder);

ObjectDecorator objectdeco =new ObjectDecorator(existdeco);
existdeco.set_creator(existBuilder);

LifeDecorator lifedeco =new LifeDecorator(existdeco);
lifedeco.set_creator(LifeBuilder);

PlantDecorator plantdeco =new plantDecorator(lifedeco);
plantdeco.set_creator(plantBuilder);

TreeDecorator treedeco =new treeDecorator(plantdeco);
treedeco.set_creator(treeBuilder);

PometreeDecorator pometreedeco =new PometreeDecorator(treedeco);
pometreedeco.set_creator(PometreeBuilder);

Pometree my_tree= pometreedeco.Create();

这个情况是可行的。现在实现一下。
首先需要规定一个creator的形式。比如它包含什么基础参数,什么公用的函数,比如add。
同时,这些LifeDecorator必须要继承于一个类,

这个父类,需要有一个属性接口,即product。

这个父类,需要有一个creator接口,即set_creator处理的。

好了。搞定!这样直接返回了一个造好的石榴树。而且我们可以调整在制造中的任何细节。同时也似乎比建造者模式要更为灵活?
这样想来,如果我们游戏中的石榴树不会有什么本体上的改变,其实无需实现这样的动态性吧?不过,那个【未来】的【石榴树】中的【未来】,肯定可以作为一个装饰器存在了。

在书本中,作者提醒我们,如果早期规划就知道会有大量的组件来扩展功能的话,那么可以用类似unity中的组件的设计方式。这个设计方式叫做ECS设计模式。

Entity Component System.

这个模式不同于组合模式,因为它只是方便增加各类组件,来实现功能,包括参数,也可以去掉组件。而组合模式会涉及到嵌套。在使用解释器的时候我们再考虑组合模式吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值