So I'm currently refactoring this "CardElement" system that had logic related to "When claim button is clicked, lockIcon object deactivates" but i want to split up this CardElement logic make a ClaimButton component class and a LockIcon component class and inject them into CardElement. But I want to make the components agnostic of each other but I still need their interaction.
What would be the best way to communicate the LockIcon component that the ClaimButton component has been clicked?
Lets say we had this Card class with a method that was called through a Unity3D button and made a reaction over ClaimButton and LockIcon, disabling them both.
public class Card {
[SerializeField] private GameObject claimButton;
[SerializeField] private GameObject lockIcon;
public void OnClaimButtonClicked() {
claimButton.SetActive(false);
lockIcon.SetActive(false);
}
}
But we want to use composite to split the logic for both claimButton and lockIcon into their own classes like so:
ClaimButton
public class ClaimButtonComponent : IComponent {
[SerializeField] private GameObject claimButton;
public event Action ButtonClickedEvent;
public void ButtonClicked() {
claimButton.SetActive(false);
ButtonClickedEvent;
}
LockIcon:
public class LockIconComponent : IComponent {
[SerializeField] private GameObject lockIcon;
public void Toggle() {
lockIcon.SetActive(false);
}
Making this, components do not know of each other.
The problem comes when I want to make it so we keep the logic related to, when clicking claimButton, lockIcon reacts accordingly without having a direct reference of lockIconComponent in claimButtonComponent.
I have thought something like storing the components through the IComponent abstraction and then, through runtime checkings, check if the Card has the specific components (since we want to make the card agnostic of what cards it has) and then, based on the ones it has, stablish the interactions between components. (I have thought out a more complex system using interaction registries and factories but this is as simple as i could get it to explain the main issue.
public Class Card {
private List<IComponent> components = new List<IComponent>();
public void Initialize() {
var claimButton = new ClaimButtonComponent();
components.add(claimButton);
var lockIcon = new LockIconComponent();
components.add(lockIcon);
HandleComponentInteractions();
}
private void HandleComponentInteractions() {
if(RetrieveComponent<ClaimButtonComponent>() != null &&
RetrieveComponent<LockIconComponent>() != null) {
HandleClaimButtonAndLockIconInteraction();
}
private T RetrieveComponent<T>() {
foreach(var component in components) {
if(component is T) {
return component;
}
return null;
}
private void HandleClaimButtonAndLockIconInteraction() {
var claimButton = RetrieveComponent<ClaimButtonComponent>();
var lockIcon = RetrieveComponent<LockIconComponent>();
claimButton.ButtonClickedEvent += lockIcon.Toggle;
}
My question is, does this way of handling composite components interactions make sense or there is a cleaner way of handling this scenario.