I want to lean how to implement a Generic Composition pattern using Flyweight. I found lots of info on Composition and Flyweight but nothing this specific ( Generic Composition pattern using Flyweight)
Please any learning resources would be appreciated
Thank you
Please help so I dont have to go to stack-overflow, people on there will eat me alive lol
What is it you’re attempting to do?
Are you trying to have it where the various child components of a composited object are flyweights themselves?
Have a flyweight source, and when you add child components to the composited object, use the flyweights you get from the flyweight source.
Yes that is what I’m trying to learn but I need to see it to understand it.
Here is one that got my head around composition
//-------------------------------------------------------------------------------------
// CompositeStructure.cs
//-------------------------------------------------------------------------------------
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CompositeStructure : MonoBehaviour
{
void Start ( )
{
// Create a tree structure
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
root.Add(new Leaf("Leaf C"));
// Add and remove a leaf
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
// Recursively display tree
root.Display(1);
}
}
/// <summary>
/// The 'Component' abstract class
/// </summary>
abstract class Component
{
protected string name;
// Constructor
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
/// <summary>
/// The 'Composite' class
/// </summary>
class Composite : Component
{
private List<Component> _children = new List<Component>();
// Constructor
public Composite(string name)
: base(name)
{
}
public override void Add(Component component)
{
_children.Add(component);
}
public override void Remove(Component component)
{
_children.Remove(component);
}
public override void Display(int depth)
{
Debug.Log(new String('-', depth) + name);
// Recursively display child nodes
foreach (Component component in _children)
{
component.Display(depth + 2);
}
}
}
/// <summary>
/// The 'Leaf' class
/// </summary>
class Leaf : Component
{
// Constructor
public Leaf(string name)
: base(name)
{
}
public override void Add(Component c)
{
Debug.Log("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Debug.Log("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Debug.Log(new String('-', depth) + name);
}
}
On a side note is ECS following a composition type structure. Is threr a structure template for ECO like the one above so I can understand how to structure for ECS
Thanks heaps
Very simple example:
//composition pattern example - a buff system
public class PlayerBuffComposite
{
private List<IBuff> _buffs = new List<IBuff>();
public void AddBuff(IBuff buff)
{
_buffs.Add(buff);
}
public void RemoveBuff(IBuff buff)
{
_buffs.Remove(buff);
}
public void ApplyBuffToAction(PlayerAction action)
{
foreach(var buff in _buffs)
{
_buffs.ApplyToAction(action);
}
}
}
public interface IBuff
{
void ApplyToAction(PlayerAction action);
}
//flyweight pattern example
public class AttackBuff : IBuff
{
public float Multiplier;
public void ApplyToAction(PlayerAction action)
{
action.AttackStrength *= Multiplier;
}
//also implement general flyweight implementation if you deem it necessary like equality
}
public class DefenseBuff : IBuff
{
public float Multiplier;
public void ApplyToAction(PlayerAction action)
{
action.Defense *= Multiplier;
}
//also implement general flyweight implementation if you deem it necessary like equality
}
public static class BuffFlyweightSource
{
public static readonly IBuff Level1AttackBuff = new AttackBuff() { Multiplier = 1.1f };
public static readonly IBuff Level2AttackBuff = new AttackBuff() { Multiplier = 1.5f };
public static readonly IBuff Level1DefenseBuff = new DefenseBuff() { Multiplier = 1.1f };
//your flyweight source could be implemented any number of ways... I just did static readonly field.
//you could have done a dictionary allowing for lookups, which would be nice since you could than use an enum/string to allow other scripts to have configurable buffs that they apply
//of course... if I was actually doing this in my game, I'd probably use a ScriptableObject as my flyweight... actually, it IS what I do in my game.
}
//usage
public class DefenseBuffItem : MonoBehaviour
{
//when the player intersects the item, add defense buff
private void OnTriggerEnter(Collider other)
{
var player = Player.GetFromCollider(other);
if(player == null) return; //wasn't the player
//here we add a flyweight as the component of the PlayerBuffs composite
player.PlayerBuffs.AddBuff(BuffFlyweightSource.Level1DefenseBuff);
//we destroy the defense item when collected
Destroy(this.gameObject);
}
}
1 Like
Thanks lordofduck is is super helpful. Just wondering what design patten is ECS or simular to it