How to separate Logic and UI scripts with dynamic buttons?

Hello,

I have one Party UI canvas that I would like to reuse for different button OnClick logic.

At the moment, I feel like my logic scripts are coupled too close to the UI and I would like to keep them separate, but also be able to pass the functions in the logic states to the UI.

Could anyone give me an idea / reference of how to do this?

I’ve got some pseudo code below of roughly what I have at the moment.

The SwitchLogic and SubstituteLogic are class states within a BattleSystem.

public class PartyUI : MonoBehaviour
{
    public delegate void OnSelected(Member member);
    public OnSelected onSelected;

    [SerializeField] Transform partyContainer;
    [SerializeField] PartySlotUI partySlotPrefab;
    private party party;

    void DrawSlots()
    {
        foreach (Member member in party.Members)
        {
            PartySlotUI slotUI = Instantiate(partySlotPrefab, partyContainer);
            slotUI.button.onClick.AddListener(() => onSelected(member));
        }            
    }
}
public class SwitchLogic : BattleState
{
    [SerializeField] PartyUI partyUI;

    public override void Enter(BattleSystem bs)
    {
        partyUI.gameObject.SetActive(true);
        partyUI.onSelected += SelectSlot;
    }

    public void SelectSlot(Member member)
    {
        Debug.Log("Switch Logic");
    }
}
public class SubstituteLogic : BattleState
{
    [SerializeField] PartyUI partyUI;

    public override void Enter(BattleSystem bs)
    {
        partyUI.gameObject.SetActive(true);
        partyUI.onSelected += SelectSlot;
    }

    public void SelectSlot(Member member)
    {
        Debug.Log("Substitute Logic");
    }
}
public class BattleSystem : MonoBehaviour
{
    public BattleState currentState;

    public SubstituteLogic substitute = new SubstituteLogic();
    public SwitchLogic switching = new SwitchLogic();

    void Start()
    {
        currentState = substitute;
        currentState.Enter(this);
    }

    void ChangeState(BattleState _newState)
    {
        currentState = _newState;
        currentState.Enter(this);
    }
}