我最近在 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 显示屏,只需对现有代码进行最少的更改即可轻松添加它。
我的代码是用 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();
}
}