本篇简要介绍一下设计模式的solid原则
并用最简单的代码概括一下
本篇代码均为typescript
S: 单一职责原则
一个类只干一个事。
反例
class Cleaner {
useVacuum(vacuum:Vacuum):void
fixVacuum(vacuum:Vacuum):boolean
}
这个清洁工出了有使用吸尘器的方法,竟然还有一门维修的手艺。
这在设计模式中是不允许的。
应该增加一个维修工来分担清洁工类的职责。
纠正
class Cleaner {
useVacuum(vacuum:Vacuum):void
}
class Repairman {
fixVacuum(vacuum:Vacuum):boolean
}
这样当需要修改维修方法的时候,就只需要修改维修工的类就行了。
O: 开闭原则
对扩展开放,对修改关闭
反例
class Repairman {
fixVacuum(vacuum:Vacuum):boolean;
fixTelevision(tv:Television):boolean;
}
class Host {
constructor(){
const repairman=new Repairman();
repairman.fixVacuum(new Vacuum());
repairman.fixTelevision(new Television());
}
}
这个维修工能修吸尘器和电视机。不过要是主人想让他再修点别的,他就要说求豆麻袋了,
要回去学一下(修改Repairman类),也是在设计模式中不怎么被允许的。虽然看起来很直观。
所以最好将可维修的东西抽象出来,然后维修工就修可维修的东西。
纠正
interface Appliance {
beRepair():boolean
}
class Vacuum extends Appliance {
beRepair():boolean
}
class Television extends Appliance {
beRepair():boolean
}
class Repairman {
repair(app:Appliance){
return app.beRepair();
}
}
经过这么一进化,只要这个东西是个家电,咱工人都能修了!。
L: 里氏替换原则
父类出现的地方,子类都可以进行替换。
反例
class Repairman{
repair(app:Appliance):Appliance{
app.isBroken=false;
return app;
};
}
class Apprentice extends Repairman {
repair(app:Appliance){
const newApp=new app.__proto__.constructor();
newApp.isBroken=false;
return newApp;
};
}
学徒学艺不精,为了完成任务,整了个新的家电送回去。这不亏死了吗?
所以对学徒最好增加个尝试修的方法,修不好就换一个。
而修理,直接就让老师傅去修理了。
纠正
class Apprentice {
private master:Repairman=new Repairman();
tryRepair(app:Appliance){
const newApp=ApplianceFactory.instance.createApp(app.type);
newApp.isBroken=false;
return newApp;
}
repair(app:Appliance){
this.master.repair(app);
}
}
用组合的方式,将师父作为学徒的属性而不是继承。维修就直接找师父。
尝试维修就整个新的。
关于输入输出的限制,在ts里语法提示已经做的很好了。
I: 接口隔离原则
给不同的类提供服务,不要一股脑儿把东西都给了。不管用不用的上。
反例
class Apprentice {
private master:Repairman=new Repairman();
study(){
this.master.teach(this);
}
}
class Wife {
private husband:Repairman=new Repairman();
steep(){
this.husband.sleep(this);
}
}
学徒和修理工老婆都会对修理工有需求。
这样写,看似没啥问题。
但是学徒却拥有了可以和师父睡觉的能力。
这是修理工老婆绝对不会允许的。也是接口隔离不允许的。
我们要修理工在面对学徒和老婆的时候扮演不一样的角色。
老婆和学徒也要拥有不同类型的修理工属性。
纠正
interface IHusband {
sleep(wife:Wife):void
}
interface IMaster {
teach(student:Apprentice):void
}
class Repairman implements IHusband,IMaster {
//functions
}
class Apprentice {
private master:IMaster = new Repairman();
}
class Wife {
private husband:IHusband = new Repairman();
}
这样一来,学徒就永远别想馋修理工的身子了。
D: 依赖反转原则
依赖抽象而不依赖具体。多用接口和抽象类。因为接口比具体更稳定。
反例
class Customer {
onApplianceBroken(app:Appliance){
if(app.brokenTimes === 1){
new Repairman().repair(app);
}else{
new Cleaner().recycle(app);
}
}
}
其实顾客只想要一个可以维修家电的人和回收家电的人。
不想管是不是维修工和清洁工。
一旦修理工不想修家电了,清洁工也不想回收家电了。
就需要调整自己的代码。(因为依赖的修理工和清洁工)
这不符合顾客是上帝的思想。也不符合依赖反转的思想。
纠正
interface IApplianceRepairman {
repair(app:Appliance):void
}
interface IApplianceRecycler {
recycle(app:Appliance):void
}
class Agent {
public static getApplianceRepairman():IApplianceRepairman;
public static getApplianceRecycler():IApplianceRecycler;
}
class Customer {
onApplianceBroken(app:Appliance){
if(app.brokenTimes === 1){
Agent.getApplianceRepairman().repair(app);
}else{
Agent.getApplianceRecycler().recycle(app);
}
}
}
这样一来,有了个负责的代理商,顾客就不用再关心到底是谁上门服务了。
总结
本文简要的用typescript语法介绍了一下solid原则。
灵活的运用这些原则,可以提升自己的架构能力和系统的可维护性。
当然开发的时候,不一定非要完全遵循这些原则,需要动态权衡。
不当之处,恳请评论指正~