设计模式漫谈系列之独孤九剑(转自sban blog)

本文介绍了软件设计中的七大原则,包括剔重、开封、替换、倒置、隔离、合聚及内向原则,旨在帮助程序员创建高质量、易于维护的软件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

如果目前没有更好的解决方案,那么可行的方案便是最好的方案。
编程如同做人,唯心无所滞方能潇洒快活。

第一剑:剔重。变量,属性,方法,类(接口,结构,枚举),模块,组件,但凡可以创建的成员(或称元素),均忌重建。编译器保证了同一访问域中变量的不可重复性。其它成员则必由程序员保证。

不创建功能雷同的方法。不创建行为类似的类。不设计意图重合的接口,但注意不要违反隔离(ISP)原则。

第二剑:开封,即开放-封闭(Open-Closed Principle,简称OCP)原则,软件实体(函数,类,模块etc)应该是可以扩展的,但却不可修改。

有一成不变的工程吗?模块的行为功能应该在需求有变或有所添加时可以扩展。但其源码却不能提供修改,即使对原始开发者。频繁重构、过度设计反无益处。

符合OCP原则的程序只通过添加代码来变化而不是通过修改已有代码。

项目几乎都具有复杂的可变性。一种可变性不应该分散到程序的各个角落里。一种可变性也不应该与另一种混淆在一起。理想情况下,一个类应该只做一件事情;一个程序员应该集中负责一个模块,让两人同做一件事情,不若让二人分做二事。团队需要协作,也需要分离。

第三剑:替换,即里氏替换原则(Liskov Substitution Principle,简称LSP)。这个原则对于从直接从面对对象语言学起的程序员来说,可能有些迷茫。LSP原则的主要机制是抽象和多态,而抽象与多态主要用继承完成。对于时下的面向对象语言,几乎所有都支持这个特性,所以不免有些混淆。

LSP的定义(也是继承机制的实现定义):若对于每一个类型S的对象S1,都存在一个类型T的对象T1,使得在所有针对T编写的程序P中,用S1替换T1之后,程序P的行为功能仍然不变,则称S是T的子类型(或称S继承了T)。

不要过度使用继承,虽然它使用起来很方便。

第四剑:倒置,即依赖倒置原则(Denpendence Inversion Principle,简称DIP)。

如果给程序添加新功能感到很为难,每一处改动都影响到其它,这便是缺乏灵活性。如果改动了其中一个模块,其它模块则出现了BUG,这便是程序的脆弱性。如果不个模块开发出来了,不能被重复利用,这便是不可复用性。造成这些的原因在于程序的藕合性太高。我们需要创建松藕合的架构。

如果两个类没有藕合关系,是为零藕合。零藕合固然最好,但往往也没有什么用途了。两个具体的类之间,经由一个类对另一个类直接引用造成了藕合,是为具体藕合。在具体藕合中,如果其中一者或两者抽象化了,便是抽象藕合。这三种藕合均是可取的。

DIP的定义:高级模块不应该依赖于底层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,二者都应该依赖于抽象。

应用DIP原则在于从具体类中分离出抽象,使用抽象藕合组合类关系。平常所说面向接口编程便在其中。翻翻.Net或Flex的类库,类的源头往往只是一个简单的接口。

应用DIP可能会产生大量的类和接口。但程序的精简玲珑又不在于文件数量多寡,多几个文件又有甚么干系,只要逻辑概念清淅便可。编程如同做人,唯心无所滞方能潇洒快活。

第五剑:隔离,即接口隔离原则(Interface Segregation Principle,简称ISP)。一个没有足够经验的系统分析架构师总是希望节省接口的数目,总是希望把一些功能相近或类似的接口合二为一,并视其为优化代码的一部分。我曾如此,对此深有深会。戒!

ISP定义:一个类对另一个类的依赖性应该建立在最小接口之上,使用多个单一的接口远胜于使用一个复杂的接口。

接口宜多不宜少。

第六剑:合聚,即合成/聚合复用原则(Composite/Aggregate Reuse Principle,简写CARP)。于新对象内部复用已有对象,纳其为一分子。CARP明显破坏继承,但实现较容易些。时下流行敏捷。但凡敏捷便离不了复用,复用的最简单方式莫过于CARP。

第七剑:内向,即迪米特法则(Law Of Demeter,简称LOD)。LOD告诫程序员不要和”陌生人说话”,只与你熟悉的朋友往来,即一对象应对其它对象有尽可能少的了解。

对于对象自身,即”我”来说,谁是”朋友”?
l 我自身(this)。
l 以参数形式传入至我的方法中的对象
l 我的实例变量直接引用的对象
l 我的实例变量如果是一个集合,那么集合的元素均是朋友。
l 我所创建的对象

不要和陌生人说话。

八,放弃。对于开封原则,事实上没有任何一个程序可以做到完全的100%的封闭,在不能封闭的时候必须有所选择,有所放弃。包括其它原则或设计模式亦是如此。如果目前没有更好的解决方案,那么可行的方案便是最好的方案。正如草根树皮不是美味,但在饥饿的情况下,也是最好的选择。

物理定律和化学反应多发生在理想情况下,但并非荒谬。这些设计模式原则也并非那么纯粹。
九,缓存。对已经加载的相同数据不应加载第二次;对已经创建的对象,如果有复用性,当缓存起来。

以下是“PackageContents.xml ”代码 <?xml version="1.0" encoding="utf-8"?> <ApplicationPackage SchemaVersion="1.0" AutodeskProduct="AutoCAD" Name="Autodesk Save to Web and Mobile" NameChs="Autodesk 保存到 Web 和 Mobile" NameCht="Autodesk 儲存至網頁版和行動版" NameCsy="Uložit do služby Autodesk Web and Mobile" NameDeu="In Autodesk Web & Mobile speichern" NameEsp="Guardar en la versión web y para dispositivos móviles de Autodesk" NameFra="Enregistrement Autodesk sur le Web et au format mobile" NameHun="Mentés az Autodesk webes vagy mobil fiókba" NameIta="Salva su Autodesk Web & Mobile" NameJpn="Autodesk Web およびモバイルに保存" NameKor="Autodesk Save to Web and Mobile" NamePlk="Autodesk Save to Web & Mobile" NamePtb="Salvar para Web e dispositivos móveis da Autodesk" NameRus="Сохранить в Autodesk в интернете и на мобильных устройствах" Description="Open and save drawings to Autodesk Cloud." DescriptionChs="打开图形并将其保存到 Autodesk 云。" DescriptionCht="開啟和儲存圖面至 Autodesk Cloud。" DescriptionCsy="Umožňuje otevírat a ukládat výkresy ve službě Autodesk Cloud." DescriptionDeu="Öffnen und speichern Sie Zeichnungen in der Autodesk Cloud." DescriptionEsp="Abra y guarde dibujos en Autodesk Cloud." DescriptionFra="Ouvrir et enregistrer des dessins sur Autodesk Cloud." DescriptionHun="Rajzokat nyithat meg vagy menthet az Autodesk Cloud szolgáltatásban." DescriptionIta="Aprire e salvare i disegni su Autodesk Cloud." DescriptionJpn="Autodesk クラウドから図面を開いたり保存したりします。" DescriptionKor="도면을 열고 Autodesk Cloud에 저장합니다." DescriptionPlk="Otwórz i zapisz rysunki w usłudze Autodesk Cloud." DescriptionPtb="Abra e salve os desenhos no Autodesk Cloud." DescriptionRus="Открытие и сохранение чертежей в Autodesk Cloud." AppVersion="3.1.8" FriendlyVersion="3.1.8" ProductType="Application" SupportedLocales="Enu|Deu|Esp|Fra|Ita|Plk|Ptb|Chs|Cht|Csy|Hun|Jpn|Kor|Rus" AppNameSpace="appstore.exchange.autodesk.com" Author="Autodesk, Inc" ProductCode="{5BF7551A-09A6-4BDD-AE1E-048104FB478C}" UpgradeCode="{7DE2392C-408E-48AF-A7F6-48E9E1CD6D05}" OnlineDocumentation="www.autodesk.com" HelpFile="./Contents/Resources/en-US/SaveToWebMobHelp.htm" HelpFileFra="./Contents/Resources/fr-FR/SaveToWebMobHelp.htm" HelpFileIta="./Contents/Resources/it-IT/SaveToWebMobHelp.htm" HelpFileDeu="./Contents/Resources/de-DE/SaveToWebMobHelp.htm" HelpFileEsp="./Contents/Resources/es-ES/SaveToWebMobHelp.htm" HelpFilePtb="./Contents/Resources/pt-BR/SaveToWebMobHelp.htm" HelpFileChs="./Contents/Resources/zh-CN/SaveToWebMobHelp.htm" HelpFileCht="./Contents/Resources/zh-TW/SaveToWebMobHelp.htm" HelpFileCsy="./Contents/Resources/cs-CZ/SaveToWebMobHelp.htm" HelpFileHun="./Contents/Resources/hu-HU/SaveToWebMobHelp.htm" HelpFileJpn="./Contents/Resources/ja-JP/SaveToWebMobHelp.htm" HelpFileKor="./Contents/Resources/ko-KR/SaveToWebMobHelp.htm" HelpFilePlk="./Contents/Resources/pl-PL/SaveToWebMobHelp.htm" HelpFileRus="./Contents/Resources/ru-RU/SaveToWebMobHelp.htm" > <CompanyDetails Name="Autodesk" Url="www.autodesk.com" Email="apps@autodesk.com" Phone=" " /> <RuntimeRequirements OS="Win64" Platform="AutoCAD*|ACADLT" SeriesMin="R24.3" /> <!-- AutoCAD 2019 to 2025 --> <Components Description="AutoCAD x64"> <RuntimeRequirements OS="Win64" Platform="AutoCAD*" SeriesMin="R24.3" SeriesMax="R25.0" /> <RegistryEntries> <RegistryEntry Key="WebMobile" Name="WebMobAppPackageVersion" Value="3.1.8" Type="REG_SZ" Flags="Create|Open" /> </RegistryEntries> <ComponentEntry AppName="adefunsstartup" Version="1.0.0" ModuleName="./Contents/AutoCAD/$(OS)/defunsstartup.lsp" LoadOnAutoCADStartup="True"> <Commands GroupName="wdcj"> <Components> <!-- 为每个DLL创建单独的ComponentEntry --> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/BW.dll" LoadOnAutoCADStartup="True"/> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/bzxl.dll" LoadOnAutoCADStartup="True"/> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/ktj.dll" LoadOnAutoCADStartup="True"/> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/ljmtj.dll" LoadOnAutoCADStartup="True"/> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/pkbz.dll" LoadOnAutoCADStartup="True"/> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/pmxlg.dll" LoadOnAutoCADStartup="True"/> <ComponentEntry ModuleName="./Contents/AutoCAD/win64/tzcl.dll" LoadOnAutoCADStartup="True"/> <!-- CUIX菜单 --> <ComponentEntry AppName="MyCUIXLoader" ModuleName="./Contents/AutoCAD/win64/wodechajian.cuix" LoadOnAutoCADStartup="True"> <Commands> <Command Global="LoadMyCUIX" Local="加载菜单"> <AssemblyMapping Name="LoadMyCUIX" Path="./Contents/AutoCAD/win64/wodechajian.cuix"/> </Command> </Commands> </ComponentEntry> </Components> 按以下 步骤操作CAD启用后插件自动加载未成功 MyPlugin.bundle/ # 主文件夹(必须以此后缀结尾) ├── Contents/ # 核心内容目录(必须) │ ├── x64/ # 64位插件目录(必须) │ │ └── MyPlugin.dll # 你的插件DLL │ ├── en-US/ # 可选:英文资源目录(如帮助文件) │ └── resources/ # 可选:图标等资源 └── PackageContents.xml # 核心配置文件(必须)
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值