设计一组类来报告不同 Alexa 设备的电池/电源状态

问题描述 投票:0回答:1

我最近在 Amazon sde2 底层设计面试中被问到以下问题,我在面试中展示了我的解决方案。我这一轮就被拒绝了。你能用任何面向对象的语言帮我解决这个问题吗?

// There are a wide variety of Alexa devices
// 1. Alexa devices that only have a speaker (Echo Dot, Echo Flex, https://www.amazon.com/dp/B07FZ8S74R)
// 2. Alexa devices that only have a screen/display (Alexa enabled Microwave or AC, https://www.amazon.com/dp/B07894S727)
// 3. Alexa devices that have both, speaker and screen (Echo Show, Echo Spot, https://www.amazon.com/dp/B08KJN3333).
// 4. Alexa devices that have neither a speaker, nor a screen (Echo Input, Echo link, https://www.amazon.com/dp/B0798DVZCY).
// 5. Alexa devices that have a speaker, but can be connected to a display (FireTV cube, https://www.amazon.com/dp/B08XMDNVX6).
// 
// Also,
// 1. Some Alexa devices that have batteries (Fire Tablets, Echo Tap, Echo Buds, https://www.amazon.com/dp/B085WTYQ4X)
// 2. Others that do not have batteries (Echo Dot, Echo Show).
//
// Design a set of classes that will report the current battery/power status to the user.
// Depending on the hardware, the response may need to be spoken, or displayed on a screen, or both.
// Also, depending on whether there is a battery or not, the status message will differ.
// For example, if the device is a Tablet which has a battery, a speaker, and a display, and currently
// it happens to be plugged in and recharging (let's say at 75%), then your code should return the following:
//      {
//          "say": "Current battery level is 75% and charging",
//          "display": "Current battery level is 75% and charging"
//      }
//
// Whereas if the device is an Echo Dot, which has a speaker but no battery and no screen,
// then your code should only return:
//      {
//          "say": "Currently plugged into wall power"
//      }
//
// and should NOT attempt to display anything (since there is no screen).
//
// For simplicity, ignore the details of speech generation and image/visual card generation, we can safely assume those are provided.
// Focus more on modeling the Alexa devices and their properties, and returning the correct responses.

我的解决方案在 C++ 中如下

class Battery
{
    int percentage;
    public:
    string getStatus()
    {
        string msg = to_string(percentage);
        return msg;
    }
};

class Power
{
    bool isCharging;
    public:
    string getStatus()
    {
        string msg = isCharging ? "" : "";
        return msg;
    }
};

enum OutputType { DISPLAY , SPEAKER };
class Output
{
    OutputType outputType;
    public:
    void print(string msg) = 0;
};

和:

class Speaker : public Output
{
  public:
  void print(string msg)
  {
    ...    
  }
};

class Display : public Output
{
  public:
  void print(string msg)
  {
   ...   
  }
};

class Device {
    public:
    virtual void printStatus() = 0;
};

class EchoDot : public Device
{
  Output* speaker;
  Power *power;
  public:
  void printStatus()
  {
     string msg = power->getStatus();
    speaker->print(msg);
  }
};

class EchoShow : public Device
{
  Output* speaker;
  Output* display;
  Power *power;
  public:
  void printStatus()
  {
    string msg = power->getStatus();
    speaker->print(msg);
    display->print(msg);
  }
};

和:

class FireTV : public Device
{
  list<Output*> outputs;
  Power *power;
  public:
  void printStatus()
  {
    string msg = power->getStatus();
    foreach output in outputs
        output->print(msg);
  }
  void addOutput(Output* output)
  {
      outputs.push_front(output);
  }
  void removeOutput(Output* output)
  {
      
  }
};

他告诉我要使设计具有可扩展性,以便明天如果有新设备推出一系列 LED 显示屏,只需对现有代码进行最少的更改即可轻松添加它。

oop design-patterns solid-principles object-oriented-analysis
1个回答
0
投票

我的代码是用 C# 编写的,我会定义这样的架构:

    public interface ISpeaker
    {
        public void SpeakMessage(string message);
    }

    public interface IDisplay
    {
        public void ShowMessage(string message);
    }

    public interface IPlugDisplay : IDisplay
    {
        bool IsConnected { get; set; }
    }

    public interface IPowerSource
    {
        bool IsPluggedIn { get; protected set; }
    }
    public interface IOutlet : IPowerSource
    {
    }

    public interface IBattery : IPowerSource
    {
        int PowerPercentage { get; set; }
    }

    public abstract class ADevice
    {
    }

    public class DeviceEcho : ADevice, ISpeaker, IOutlet
    {
        private bool _connected = true;//In order to work it must be plugged in
        public DeviceEcho() { }

        public bool IsPluggedIn { get { return _connected; } set { } }

        public void SpeakMessage(string message)
        {
            Console.WriteLine("Say - " + message);
        }
    }

    public class DeviceAC : ADevice, IDisplay, IOutlet
    {
        private bool _connected = true;//In order to work it must be plugged in
        public DeviceAC()
        {
        }
        public bool IsPluggedIn { get { return _connected; } set { } }

        public void ShowMessage(string message)
        {
            Console.WriteLine("Display - " + message);
        }
    }

    public class DeviceFireTablet : ADevice, ISpeaker, IDisplay, IBattery
    {
        public DeviceFireTablet(int powerPercentage, bool isPluggedIn)
        {
            this.PowerPercentage = powerPercentage;
            this.IsPluggedIn = isPluggedIn;
        }

        public int PowerPercentage { get; set; }

        public bool IsPluggedIn { get; set; }

        public void ShowMessage(string message)
        {
            Console.WriteLine("Display - " + message);
        }

        public void SpeakMessage(string message)
        {
            Console.WriteLine("Say - " + message);
        }
    }
    public class DeviceLink : ADevice, IOutlet
    {
        private bool _connected = true;//In order to work it must be plugged in
        public DeviceLink()
        {
        }
        public bool IsPluggedIn { get { return _connected; } set { } }
    }


    public class UseDevice
    {

        private ADevice m_device;
        public UseDevice(ADevice device)
        {
            m_device = device;
        }
        public void ShowStatus()
        {
            string messageBuilder = "Currently plugged into wall power";
            if (m_device is IBattery)
                messageBuilder = ((IPowerSource)m_device).IsPluggedIn ? $"Current battery level is {((IBattery)m_device).PowerPercentage}% and charging" :
                    $"Current battery level is {((IBattery)m_device).PowerPercentage}%  and discharging";
            if (m_device is ISpeaker)
                ((ISpeaker)m_device).SpeakMessage(messageBuilder);


            if (m_device is IPlugDisplay && ((IPlugDisplay)m_device).IsConnected)
                ((IPlugDisplay)m_device).ShowMessage(messageBuilder);
            else
                if (m_device is IDisplay)
                ((IDisplay)m_device).ShowMessage(messageBuilder);
        }
    }
    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("-- DeviceEcho --");
            new UseDevice(new DeviceEcho()).ShowStatus();

            Console.WriteLine();
            Console.WriteLine("-- DeviceAC --");
            new UseDevice(new DeviceAC()).ShowStatus();

            Console.WriteLine();
            Console.WriteLine("-- DeviceFireTablet on batteries --");
            new UseDevice(new DeviceFireTablet(75, false)).ShowStatus();

            Console.WriteLine();
            Console.WriteLine("-- DeviceFireTablet plugged in --");
            new UseDevice(new DeviceFireTablet(75, true)).ShowStatus();

            Console.WriteLine();
            Console.WriteLine("-- DeviceLink - no message --");
            new UseDevice(new DeviceLink()).ShowStatus();
        }

    }
© www.soinside.com 2019 - 2024. All rights reserved.