简体   繁体   English

C# 状态模式私有 ChangeState

[英]C# State-Pattern private ChangeState

I´m trying to implement the State-Pattern using C# following this page .我正在尝试在此页面之后使用 C# 实现状态模式。 Here the UML of a State-Pattern.这里是状态模式的 UML。

在此处输入图像描述

The State it self sets the new sate in the context class. State 在上下文 class 中自行设置新状态。 But here is my problem: I want to use Interfaces but the ChangeState-Method should not be present to the client but available for the state.但这是我的问题:我想使用接口,但 ChangeState-Method 不应该出现在客户端,但可用于 state。 But I don´t know how to implement a private interface within a class which I present for the client.但我不知道如何在我为客户提供的 class 中实现私有接口。

Here my first shot of the pattern Context-Class which should implement the IChangeState interface:这是我应该实现 IChangeState 接口的模式 Context-Class 的第一张照片:

public interface IContext 
{
    string Input { get; set; }
    void DoTransition();
}

public class Context : IContext
{ 
    public string Input { get; set; }

    private AbstractState _state;

    public void DoTransition() 
    {
        _state.DoTransition();
    }
}

And the IChangeState interface which does the main trick but should not be visibile to the client.和 IChangeState 接口,它起到了主要作用,但对客户端不应该是可见的。 So I assumed to make it private but how to share this interface with the state or even implement it?所以我假设它是私有的,但是如何与 state 共享这个接口,甚至实现它?

public interface IChangeState 
{
    void ChangeState(IState state);
}

And at least the States:至少在美国:

public interface IState 
{
    void DoTransition();
}

public abstract class AbstractState : IState 
{
    private IChangeState _stateChanger;

    public AbstractState(IChangeState stateChanger) => _stateChanger = stateChanger;

    public virtual void DoTransition() 
    {
        _stateChanger.ChangeState(new NextState(_stateChanger));
    }
}

public class NextState : AbstractState 
{
    public NextState(IChangeState stateChanger) 
        : base(stateChanger)
    { }

    public override void DoTransition()
    {
        base.DoTransition();
    }
}

You can make the IChangeState internal if the client is in a different assembly.如果客户端位于不同的程序集中,您可以将 IChangeState 设为内部。 The solution should look as follow:解决方案应如下所示:

        //Start Assembly MyAssembly1

        public interface IContext 
        {
            string Input { get; set; }
            void DoTransition();
        }

        internal interface IChangeState 
        {
            void ChangeState(IState state);
        }

        public class Context : IContext, IChangeState
        { 
            public string Input { get; set; }

            private IState _state;

            public void DoTransition() 
            {
                _state.DoTransition();
            }

            void IChangeState.ChangeState(IState state) {
                _state = state;
            }
        }

        public interface IState 
        {
            void DoTransition();
        }

        internal abstract class AbstractState : IState 
        {
            private IChangeState _stateChanger;

            public AbstractState(IChangeState stateChanger) {
                _stateChanger = stateChanger;
            }

            public virtual void DoTransition() 
            {
                _stateChanger.ChangeState(new NextState(_stateChanger));
            }
        }

        internal class NextState : AbstractState 
        {
            public NextState(IChangeState stateChanger) 
                : base(stateChanger)
            { }

            public override void DoTransition()
            {
                base.DoTransition();
            }
        }

        // End Assembly MyAssembly1

        // Start Assembly MyAssembly2

        public class AClient {
            private IContext _context;
            public AClient(IContext context)
            {
               _context = context;
               // ((Context)_context).ChangeState is not visible
            }
        }

        // End Assembly MyAssembly2

In this way the AClient class cannot see the methods exposed by the interface IChangeState, even if you inject a Context object instead of the IContext interface这样AClient class就看不到接口IChangeState暴露的方法了,即使你注入一个Context object而不是IContext接口

I´ve solved the issue with partial classes.我已经用部分类解决了这个问题。 There are all States and there Interfaces private so the Context-Class has access to all the interfaces and classes but the client not.所有的状态和接口都是私有的,所以上下文类可以访问所有的接口和类,但客户端不能。 The IChangeState-Interface I´ve implemented in a seperate Class which is also private so only the Context can change the state.我已经在单独的 Class 中实现了 IChangeState-Interface,它也是私有的,因此只有上下文可以更改 state。 Example as followed:示例如下:

public interface IContext 
{
    string Input { get; set; }
    void DoTransition();
}

public partial class Context : IContext
{ 
    public string Input { get; set; }
    private IChangeState _stateChanger;
    
    public void DoTransition() 
    {
        _stateChanger.CurrentState.DoTransition();
    }
}

public partial class Context
{   
    private interface IChangeState 
    {
        IState CurrentState { get; }
        void ChangeState(IState state);
    }
}    

public partial class Context
{   
    private class ChangeState 
    {
        IState CurrentState { get; private set; }
        void ChangeState(IState state) 
        {
            CurrentState = state;
        }
    }
} 

public partial class Context
{
    private interface IState 
    {
        void DoTransition();
    }
}

public partial class Context
{   
    private abstract class AbstractState : IState 
    {
        private IChangeState _stateChanger;
    
        public AbstractState(IChangeState stateChanger) => _stateChanger = stateChanger;
    
        public virtual void DoTransition() 
        {
            _stateChanger.ChangeState(new NextState(_stateChanger));
        }
    }
}

public partial class Context
{
    private class NextState : AbstractState 
    {
        public NextState(IChangeState stateChanger) 
            : base(stateChanger)
        { }
    
        public override void DoTransition()
        {
            base.DoTransition();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM