我需要更改哪些内容才能正确实施 SOLID 设计?

     2023-03-15     265

关键词:

【中文标题】我需要更改哪些内容才能正确实施 SOLID 设计?【英文标题】:What do I need to change to implement SOLID design correctly? 【发布时间】:2019-10-20 11:09:02 【问题描述】:

我正在尝试学习 SOLID 设计,但我认为我犯了一个错误。我认为IItem 接口在我的Player 类中不遵循Liskov 替换原则,但是我不知道如何解决这个问题。如果我从 IItem 添加一个新的界面绘图,我将不得不更改 Player 的方法以添加一个案例来处理它。

我希望 Player 类只需要一种装备方法,因此需要帮助了解我做错了什么以及如何正确做。

我的界面的简化版:

    interface IItem
    
        string Name  get; set; 
        int Value  get; set; 
        Quality Quality  get; set; 
        EquipmentType Type  get; set; 
    
    interface IWeapon : IItem
    

    
    interface IArmour : IItem
    
        int Defence  get; set; 
        Slot Slot  get; set; 
    

消费类 Player 类:

    class Player
    
        private Dictionary<Slot, IArmour> armour = new Dictionary<Slot, IArmour>();
        private IWeapon weapon;

        public bool Equip(IItem item)
        
            switch (item.Type)
            
                case EquipmentType.Armour:
                    var armour = item as IArmour;
                    if (this.armour.ContainsKey(armour.Slot))
                    
                        return false;
                    
                    this.armour.Add(armour.Slot, armour);
                    return true;
                case EquipmentType.Weapon:
                    var weapon = item as IWeapon;
                    throw new NotImplementedException();
                default:
                    return false;
            
        
    

上下文枚举:

    enum Slot
    
        Head = 0,
        Soulders = 1,
        Gloves = 2,
        Neck = 3,
        RRing = 4,
        LRing = 5,
        Torso = 6,
        Legs = 7,
        Boots = 8,
        Bracers = 9,
        Belt = 10,
    
    enum EquipmentType
    
        Armour = 0,
        Weapon = 1
    

【问题讨论】:

是什么让你认为你在这里破坏了 LSP? @canton7 如果我以后从 IItem 添加一个新的派生接口,我将不得不更改播放器,据我了解这意味着它是不可替代的? 这里看起来更像是打开/关闭违规(SOLID 的“O”),而不是 Liskov 替换问题。如果您需要进行更改,则意味着您的代码没有关闭进行修改。 @Corentin Pane,好点子!你能给我什么建议让我回到正轨吗?我还在努力学习:) 如果你有一个派生自例如的类,你会破坏 LSP。 IArmor(我们称它为Shield),如果您使用IArmor 引用它,则该类的行为与使用Shield 引用它时的行为不同。如果有的话,这违反了打开/关闭原则,因为如果您添加另一种类型的设备,您需要修改您的 Player 类以正确处理它(以及使用 EquipmentType 的所有其他地方)。但是我不会在这里担心 - 如果您添加一种新型设备,您的 Player 很可能需要一些升级来应对 【参考方案1】:

Liskov 替换原则 通常与您如何定义类有关。如果您编写一个派生自其他类(或实现某个接口)的类,则想法是有人应该能够使用您的类,就好像它是该父类的实例一样。您的子类可能具有父类没有的其他行为(当然,将您的类当作父类的实例使用的人将无法访问它),但是所有行为父类在子类中应该保持原样。

在您的示例中,这可能意味着定义不适合 SlotMagicalWholeBodyArmor,因此如果您尝试访问其 Slot 属性,则会引发异常。将MagicalWholeBodyArmor 视为IArmor 的人在尝试查看它适合哪个插槽时会大吃一惊。

您编写的代码确实违反了 SOLID 规则,即 开放/封闭原则。 Open/Closed 原则的一个很好的经验法则是“如果我更改这段代码,我还必须更改其他地方的多少其他代码位?”。如果答案是“很多”,那可能是因为您违反了开放/封闭原则。

在您的情况下,添加一个新的 EquipmentType 枚举成员意味着您必须在 Player 类中找到该 switch 语句并添加一个新的情况。

如果只有一个 switch 语句,那还不错。如果您添加了一种新型设备,那么您的Player 类可能需要升级无论如何,因此修改 switch 语句作为其中的一部分是可以的。尝试以自己的方式解决这个问题将意味着大量的抽象,而收益却很少。

但是,如果您在许多不同的地方有很多很多 switch 语句,它们都在查看 EquipmentType,(并根据它做出不同的决定),那么您需要找到它们并全部修复它们,那么这就更严重地违反了开放/封闭原则,这可能表明您需要重新架构事物以将所有这些独立的、不同的逻辑位集中到一个地方。

【讨论】:

适用于java开发人员的solid设计原则简介

...么要SOLID?”的整个概念,以及如何实施设计模式,这需要时间和大量实践。我可以说实话,关于SOLID设计模式以及TD 查看详情

佰新视觉ui设计的实施需要注意哪些问题

...设计培训的小伙伴想要做的网页设计得更漂亮、更精致,需要注意哪些方面?   网站视觉设计的实施需要注意哪些问题。  一,布局简约大方。  设计者要注意的是,只有保证网页设计布局简约大方,才能减少用户... 查看详情

此 package.json 文件需要更改哪些内容才能使用 npm 0.3.0?

】此package.json文件需要更改哪些内容才能使用npm0.3.0?【英文标题】:Whatneedstochangeinthispackage.jsonfiletoworkwithnpm0.3.0?【发布时间】:2011-08-0409:41:39【问题描述】:尝试使用lib但出现此错误...npmERR!JSON.parseFailedtoparsepackage.jsondata.npmERR!... 查看详情

必须在客户端或服务器端更改哪些内容才能使 getJSON() 工作?

...:48【问题描述】:我正在使用一些已经创建的Web服务,我需要使用ajax调用它们。我正在处理的站点托管在与Web服务不同的域中。我现在知道这会导致同源策略的问题。我正在尝试使用JSON来解决 查看详情

我需要进行哪些更改才能执行上界的反转?

】我需要进行哪些更改才能执行上界的反转?【英文标题】:WhatisthechangeIneedtomaketoperformreverseofupper_bound?【发布时间】:2021-12-1219:45:31【问题描述】:我觉得c++stl中的lower_bound与upper_bound函数并不相反。默认情况下,在非递减数组... 查看详情

PHP 文件不会在浏览器中打开 - 只能下载。我需要进行哪些更改才能使其正常工作?

】PHP文件不会在浏览器中打开-只能下载。我需要进行哪些更改才能使其正常工作?【英文标题】:PHPFileswon\'topeninbrowser-onlydownload.WhatdoIneedtochangetomakeitworkproperly?【发布时间】:2011-07-2019:51:40【问题描述】:我已尝试重新安装PHP... 查看详情

所有 Python dunder 方法的列表 - 您需要实现哪些方法才能正确代理对象?

】所有Pythondunder方法的列表-您需要实现哪些方法才能正确代理对象?【英文标题】:ListofallPythondundermethods-Whichonesdoyouneedtoimplementtocorrectlyproxyanobject?【发布时间】:2019-10-0720:19:09【问题描述】:我正在尝试创建一个对象代理。属... 查看详情

需要进行哪些更改才能使此代码检测多个人脸而不是仅一个人脸

】需要进行哪些更改才能使此代码检测多个人脸而不是仅一个人脸【英文标题】:whatchangeisnecessarytomakethiscodedetectmultiplefacesratherthanonlyone【发布时间】:2018-08-1112:36:27【问题描述】:我是openCV和dlib模块的新手。我试图让这段代码... 查看详情

如何设计遵循 SOLID 的类而不在其他地方加载违反 SOLID 的内容?

】如何设计遵循SOLID的类而不在其他地方加载违反SOLID的内容?【英文标题】:HowcanIdesignclassesthatfollowSOLIDwithoutoffloadingviolationsofSOLIDsomewhereelse?【发布时间】:2017-12-2203:41:30【问题描述】:我的控制器违反了开闭原则。我试图弄清... 查看详情

需要在上下文类中进行哪些更改才能将连接字符串移动到 appsettings.json 文件中

】需要在上下文类中进行哪些更改才能将连接字符串移动到appsettings.json文件中【英文标题】:Whatchangesneedtobemadeincontextclasstomoveconnectionstringintoappsettings.jsonfile【发布时间】:2021-09-0623:09:22【问题描述】:我正在使用.NETCOREWEBAPI项... 查看详情

我应该在 app.json 文件中更改哪些内容以从 expo 重建我的应用程序?

】我应该在app.json文件中更改哪些内容以从expo重建我的应用程序?【英文标题】:WhatshouldIchangeintheapp.jsonfiletorebuildmyappfromexpo?【发布时间】:2020-03-1619:53:57【问题描述】:我计划重建我的应用程序。应该更改哪些设置才能从1.0.0... 查看详情

我需要在文件“/etc/php5/apache2/php.ini”中更改哪些内容以显示错误、警告、异常?我应该如何保存我所做的更改?

】我需要在文件“/etc/php5/apache2/php.ini”中更改哪些内容以显示错误、警告、异常?我应该如何保存我所做的更改?【英文标题】:Where&whatIneedtochangeinafile\'/etc/php5/apache2/php.ini\'todisplayerrors,warnings,exceptions?HowshouldIsavethechangesImade... 查看详情

如果维度/事实表中的数据未正确加载,我需要执行哪些步骤来清理数据

】如果维度/事实表中的数据未正确加载,我需要执行哪些步骤来清理数据【英文标题】:whatarethestepsIneedtoperformtocleanthedataifdataintothedimension/facttableimproperlyloaded【发布时间】:2020-11-0714:18:29【问题描述】:假设有一个场景,有一... 查看详情

erp系统成本包括哪些方面

...实施成本  必须由专业人员安装和配置ERP系统,因此您需要将这些实施成本包括在ERP系统的总价中。ERP系统是复杂的软件应用程序,因此您可能需要更改操作系统,升级或更改服务器以及更改在公司网络上使用的其他硬件和软... 查看详情

在 WebdriverIO 中,为啥 `expect` 行需要在其前面加上 `await` 才能正确测试某些内容?

】在WebdriverIO中,为啥`expect`行需要在其前面加上`await`才能正确测试某些内容?【英文标题】:InWebdriverIO,whydoesthe`expect`linerequirean`await`infrontofittocorrectlytestsomething?在WebdriverIO中,为什么`expect`行需要在其前面加上`await`才能正确测... 查看详情

轨道加密/解密

...n/decryption【发布时间】:2012-01-2307:46:42【问题描述】:我需要在我的Rails应用程序中进行加密和解密。我尝试使用ezcrypto,但每当我解密时都会出现此错误。OpenSSL::Cipher::CipherErrorinProfilesController#showwrongfinalblocklength需要更改哪些内... 查看详情

为了重新排列 UITableView 行,我必须实施哪些方法?

...示例,我必须在表控制器中实现什么来移动tableView行并将更改反映在我的数组中?【问题讨论】:【参考方案1】 查看详情

您需要来自计算机管理员的权限才能对此文件夹进行更改

...无法访问C:\……拒绝访问;2、删除文件夹时提示:您需要来自计算机管理员的权限才能对此文件夹进行更改。求助:删除这个垃圾管理员权限设置方法:1、选择文件夹或文件所有者用鼠标右键点击要操作的文件或文件夹,依... 查看详情