首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >面向对象的通用设备建模设计

面向对象的通用设备建模设计
EN

Stack Overflow用户
提问于 2021-12-22 14:25:26
回答 3查看 302关注 0票数 5

在一次访谈中,我被问到了以下面向对象的系统设计问题。

有多种设备,如回声显示、回声点、回波标签、智能微波、火电棒等。

  • 回声显示-它有显示屏幕和扬声器。它工作在电源上。
  • 回声点-它有扬声器。它工作在电力供应。
  • 回声标签-它有扬声器。它适用于电池供应。电池可以充电。
  • 智能微波炉-它有屏幕显示。它工作在电力供应。
  • 消防电视棒-它有扬声器。它适用于电力供应。

因此,基本上这些是3类,如-扬声器/屏幕显示/扬声器和屏幕显示,有两类,如-供电/电池供应。可以在任何这些设备上进行查询,比如打印状态。以下是每个设备的可能输出-

  • Echo节目--“它在充电”或“它没有充电”,这取决于它是否接通了电力供应。这个输出应该出现在屏幕和speaker.
  • Echo点上--“它在充电”或“它没有充电”,这取决于它是否连接到电力供应。这个输出应该出现在speaker.
  • Echo标签上--“电池正在充电”或“电池没有充电,电池水平是70%”,这取决于电池是否充电。这个输出应该是在speaker.
  • Smart微波上--“它在充电”或者“它没有充电”,这取决于它是否连接到电力供应。这个输出应该出现在屏幕上。
  • 消防电视棒-“它在充电”或“它没有充电”取决于它是否连接到电力供应。这个输出应该是扬声器的。

假设有内置的在屏幕上讲话和打印的类。如果我们将字符串传递给这些类对象,它们将执行各自的工作。

现在编写4-5个类来建模这个场景。

设计应该是可扩展的,如果明天任何新的设备都有一个新的组合,那么它就可以实现,而无需创建任何新的类。因此,您不应该为每个设备创建类。

这是我的面向对象的解决方案,但面试官对此并不满意,尤其是vector<Output*> outputs。他建议使用一些设计模式,而不是矢量。你能想出更好的解决办法吗?

代码语言:javascript
复制
class Output {
   public:
    virtual void print(string);
};
class Display : public Output {
    DisplayScreen obj;
   public:
      void print(string str) { obj.print(str); }
};
class Speaker : public Output {
    Audio obj;
   public:
      void print(string str) { obj.print(str); }
};
class PowerSupply {
   public :
    virtual string get_status();
};
class BatteryPower : PowerSupply {
   bool isCharging;
   int chargeLevel;
   public :
     string get_status();
};
class ElectricPower : PowerSupply {
   bool isCharging;
   public :
     string get_status();
};
class Device {
    vector<Output*> outputs;//I used vector because Echo show has both display and speaker
    PowerSupply powersupply;
    Device(vector<Output> &outputs, PowerSupply powersupply) {
        this->outputs = outputs;
        this->powersupply = powersupply;
     }
};
EN

回答 3

Stack Overflow用户

发布于 2021-12-22 14:46:45

vector<Output>不允许继承,因为它直接存储Output的指针或引用。如果将DisplaySpeaker存储在向量中,则为sliced

由于每个设备的输出都是唯一的,所以我会将其作为唯一指针的向量:

代码语言:javascript
复制
std::vector<std::unique_ptr<Output>> outputs;
票数 4
EN

Stack Overflow用户

发布于 2021-12-27 10:11:47

我不认为面试官要求使用某种设计模式是有任何建设性的。设计模式是完成某事的工具;没有目标,设计模式就毫无意义。相反,他可能会说:“我们预计将不得不用最小的偏差建造许多类似的设备。你将如何做到这一点?”在“现在标签的随机设计模式和我们是黄金”。

除了技术问题,John Kugelman answered here。我认为有几种设计模式,你可以使用,而不仅仅是传递一个矢量的设备和电源。我头顶上的一些例子:

工厂模式

研究关键词:工厂模式

代码语言:javascript
复制
class DotFactory
{
    DotFactory(/*maybe you need parameters*/);
    Device* getDevice(/*more parameters e.g. speaker count*/);
}

建造者模式

研究关键词:构建器模式

根据复杂性和用例,您可以将设备构建器集成到设备中。为了简单起见,我是这样做的。

代码语言:javascript
复制
class Device 
{
    // Your stuff
    vector<Output*> outputs;
    PowerSupply powersupply;
    Device(vector<Output*> &outputs, PowerSupply *powersupply);

    // Builder functions
    bool addPowerSupply(PowerSupply*);
    bool addOutput(Output*);

    // If outside your Device class also integrate:
    Device* getBuiltDevice();
};

更多的模式和组合(我本来想出一个以上的。也许有人可以编辑更多。)

单例设备列表(大多数情况下是反模式的)

根据使用程序的不同,您也可以拥有任何东西(方法、容器、类等)。持有您的预定义‘设备’,如果您只需要每个应用程序一个。

票数 1
EN

Stack Overflow用户

发布于 2021-12-30 22:07:19

我建议介绍以下5门课程:

用于电源状态的

  • PowerStatusProvider ->接口/策略类和用于所有事物的such
  • BatteryStatus ->具体实现--电池powered
  • WiredStatus -> --由wire
  • OutputHandler ->发布状态驱动的所有事物的具体实现--使用所提供的服务(屏幕、Speaker)
  • Device -> --对小工具

的实际抽象)

我用structs代替了类来缩短符号。通过依赖注入函子获取电池电平。C++20有std::format,也许您的编译器也有。

代码语言:javascript
复制
// Assuming Screen and Speaker are provided in a common interface 
struct OutputDevice{
    virtual void publish(std::string const & output) = 0;
    virtual ~OutputDevice()=default;
}

using OutputDevice_sp = std::shared_ptr<OutputDevice>;

struct Screen : OutputDevice{
    void publish(std::string const & output) override {
        // ...
        };
};

struct Speaker : OutputDevice{
    void publish(std::string const & output) override {
        // ...
        };
};

/// Here goes the actual implementation

struct PowerStatusProvider{
    virtual std::string to_string(bool Connected) const = 0;
    virtual ~PowerStatusProvider()=default;
};

struct BatteryStatus : PowerStatusProvider{
    BatteryStatus(std::function<double()> BatteryLevelProvider)
    : mBatteryLevelProvider(BatteryLevelProvider){}
    
    std::string to_string(bool Connected) const override
    {
        if (Connected)
            return "Battery is charging";
        else
            return std::format("Battery is not charging and battery level is {}%",mBatteryLevelProvider());
    }
private:
    std::function<double()> mBatteryLevelProvider;
};

struct WiredStatus : PowerStatusProvider{
    std::string to_string(bool Connected) const override
    {
        if (Connected)
            return "Device connected";
        else
            return "Device not connected";
    }
};

struct OutputHandler{
    OutputHandler(std::vector<OutputDevice_sp> Outputs)  
    : mOutputs(Outputs) {}
    
  void handle(std::string const & output) const {
      for (auto &&output : mOutputs) {
          output->publish(output);
      }
  } 

private:
    std::vector<OutputDevice_sp> mOutputs;
};

using PowerStatusProvider_sp = std::shared_ptr<PowerStatusProvider>;
using OutputHandler_sp = std::shared_ptr<OutputHandler>;


struct Device{
    struct Device(std::string Name, PowerStatusProvider_sp PSP, OutputHandler_sp OH)
    : mName(Name)
    , mPSP(PSP)
    , mOH(OH) 
    {}

    void update_status() const{
        mOH->handle(mPSP->to_string());
    }
  
private:
    std::string mName;
    std::shared_ptr<PowerStatusProvider> mPSP;
    std::shared_ptr<OutputHandler> mOH;
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70450543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档