阅读 40

设计模式分为哪三大类,六大类设计模式

软件设计的最大挑战是适应需求的变化,我们往往对这些变化感到困惑。 面临系统难以修改或扩展、代码过于复杂、重复码多、公共码不能复用、系统不稳定、修改结束后经常出现错误等一系列问题。 要实现系统的可扩展性、复用性、灵活性、维护性等,需要良好的设计模式。 今天首先介绍设计模式应该遵循的六个原则。

第一:单一职责原则(SPR)

先看看场景吧。 一个类包含两个责任T1-T2。如果需要根据责任t1的需要修改类,则很可能会影响正在运行的责任T2。 因此,就会出现单一作用的概念。 这就是说,一个类应该具有的概念,而且引起该类变更的原因只有一个。 换句话说,一个类应该只承担一个作用,该类的变更智能是由该作用引起的。

单一的职责告诉我们,一个班级不能太“累”! 包含模块和方法的类的责任越多,它被复用的可能性就越低。 而且,一个类承担的作用过多就相当于把这些作用放在一起,因为一个作用的变化可能削弱或抑制该类发挥其他作用的能力,所以这种结合是非常不利的。 我们要做的是分离角色,将不同的角色封装在不同的类中。

举个例子:

/* *很明显,此接口具有两个角色:连接管理和数据传输* /公共视频(string pno )。 公共void hang up (; 公共void send (charc; 公共语音记录(; }如果连接管理或数据传输发生更改,此类也会发生更改,因此上述接口违反了单一责任原则。 /* *负责管理连接的接口*/publicinterfaceconnenction { public void dial (string pno ) }; 公共void hang up (; }

/* *负责数据传输的接口*/publicinterfacedatachannel { public void send (charc ); 公共语音记录(; }

现在总结一下,SRP的好处是消除耦合,减少需求变化导致的代码僵化问题。 SRP强调基于角色来衡量接口和类,但往往因项目而异,因为角色定义不明确。 在合理的类别中,尽量只因一个原因而引起其变化; 但接口必须履行单一职责; 当需求发生实际变化时,应该使用SRP等原则重建代码。

第二:mgdsb替换原则(LSP)

mgdsb替换策略的概念必须是能够在引用基类的所有地方透明地使用子类的对象。 这意味着只要父类出现在某个地方,子类就会出现,而用子类替换时不会出现错误或异常。 因此,程序会尽量使用基类类型来定义对象,在运行时确定子类类型,然后用子类对象替换父类类型。 但是,有子类出现的地方,父类不一定能适应。

使用LSP时,请注意以下事项:

)1)子类必须完全实现父类的方法,并在程序中使用父类定义对象。 如果一个方法只存在于子类中,则对于父对象,该方法的不可用。 如果子类不能完全实现父类的方法,请考虑分离继承关系,并采用依赖集组合等关系来代替继承。

)使用LSP时,尽量将父类设计为接口或抽象类,使子类继承父类或父类的接口,并实现在父类中声明的方法。 当子类的实例在运行时代替父类的实例并进行系统扩展时,不需要修改以前子类的代码,只需添加新子类并实现即可。

)3)子类可以在覆盖或实现父类的方法时扩展输入参数。 这意味着,要执行子类的方法,必须重写父类的方法。 此外,还可以重载此方法。 但是,前提是子类的参数范围大于父类的参数范围。

)4)重写或实现父类方法时的输出结果类型必须小于或等于父类的输出结果。

Father.java

public class father { public void show (inti ) system.out.println; }公共对象显示1 () {return '父类); }publicvoidshow2(Hashmapmap ) {System.out.println ('父类); } son.javapublicclasssonextendsfather { public void show (inti ) {System.out.println子类重写了父类的show '。 system.out.println(I; }public String show1(() {return '11 ); }publicvoidshow2(mapmap ) {System.out.println )子类); }}main1.java/* * mgdsb替换原则LSP *重写(override )和重载(overload ) )重写,即子类如何重写父类,方法的名称和列表完全匹配*重载通常发生在类中,但子类在继承父类时也会重载。 但是,为了允许子类在不重写父类的情况下运行,*也就是说,不能重载子类。 因此,发生重载时,必须确保子类的参数范围大于父类的参数范围*子类将重写父类方法,并且返回值可以不相同,但父类的返回类型为子类

父类,重载也一样 * 必须保证父类的返回值类型是子类的返回值类型父类。 */public class main1 {public static void main(String[] args){HashMap map=new HashMap<>();Father f=new Father();//f.show(1);System.out.println(f.show1());//f.show2(map);Son s=new Son();//s.show(1);System.out.println(s.show1());//s.show2(map);}}介绍一个mgdsb替换的例子:


客户(customer)可以分为VIP客户(VIPCustomer)和普通客户(CommonCustomer)两类,系统需要提供一个发送邮件的功能,初始设计如下:


我们可以看到两个send发送的过程都是一样的,说明这个代码是重复的,而且如果再增加新的类型的客户,则要再增加一个一样的send方法。为了让系统有更好的扩展性,使用mgdsb替换原则进行重构。修改方案是新增加一个抽象客户类Customer,让VIP客户和普通客户作为其子类,设计如下:


mgdsb替换原则能够保证系统具有良好的扩展性,同时实现基于多态的抽象机制。子类必须满足基类和客户端对其行为的约定。

第三:依赖倒置原则(DIP)

依赖倒置原则指的是(1)模块之间的依赖是通过抽象发生的,实现类之间不能直接的依赖关系,实现类的依赖关系是通过接口或者抽象类产生的;(2)接口或者抽象类不依赖于实现类(3)实现类要依赖接口或者抽象类。或者更加精简的定义是依赖倒置原则是面向接口编程。

依赖倒转原则要求我们在程序代码中传递参数时或者在关联关系中,尽量引用层次高的抽象类,即用接口和抽象类进行变量类型的声明、参数类型声明、方法返回类型声明以及数据类型的转换等,而不使用具体的类来做这些事情。在引入抽象以后,系统具有很好的灵活性,在程序中尽量使用抽象层进行编程,当系统行为发生变化时,只需要对抽象层进行扩展即可,不需要修改原有系统的代码。

依赖倒置的本质就是通过抽象使各个类或模块的实现彼此独立,实现模块之间的松耦合。在使用依赖倒置原则时要注意(1)每个类尽量都有接口或抽象类,因为有了抽象才能依赖倒置。(2)变量的表面类型尽量是接口或者是抽象类。注意的是工具类一般是不需要接口或者抽象类的。(3)任何类都尽量的不能从具体类派生(4)尽量不要重写父类的方法,如果基类是一个抽象类,而且这个方法已经实现了,子类尽量的不要重写。

在实现依赖倒置原则时,我们需要对抽象层编程,而将具体类的对象通过依赖注入的方式注入到其他对象中。依赖注入指的是一个对象与其他对象发生依赖关系时,通过抽象来注入依赖对象。依赖注入有三种方式,包括构造函数注入、设置(setter)注入和接口注入,常用的就是前两种。

(1)构造注入,即通过构造函数来传入具体类的对象。如下:

public class UserRegister { private UserDao userDao =null;//由容器通过构造函数注入的实例对象 publicUserRegister(UserDao userDao){ this.userDao =userDao; }}(2)Setter设置注入,即在抽象中设置Setter方法声明依赖关系,如下:public interface InjectUserDao { public void setUserDao(UserDao userDao);}public class UserRegister implementsInjectUserDao{ private UserDao userDao = null;//该对象实例由容器注入 public void setUserDao(UserDao userDao) { this.userDao = userDao; }}(3)接口注入,即在接口的方法中声明依赖对象,如上面的InjectUserDao就属于接口注入。


第四:接口隔离原则(ISP)

接口隔离原则指的是使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。接口要尽量的细化,同时接口中的方法尽量少。一般而言,接口中仅包含为某一类用户定制的方法即可。

第五:ggdbmh法则(LoD)

ggdbmh法则指的是一个软件实体应当尽可能少的与其他实体发生相互作用。ggdbmh法则可以降低系统的耦合度,使类与类之间保持松耦的耦合关系。即只和朋友交流。对于一个对象,它的朋友包括当前对象本身、当前对象的成员对象、如果当前对象的成员对象是一个集合那么集合中的元素也是朋友、当前对象所创建的对象,出现在方法体内的类不属于朋友类,类与类之间的关系是建立在类间的,而不是方法间。

第六:开闭原则

一个软件实体应当对扩展开闭,对修改关闭。即实体软件应尽量在不修改原有代码的情况下进行扩展。抽象化是开闭原则的关键。开闭原则是最基础的一个原则,对于其他五个原则来说,开闭原则属于抽象类,其他五个原则属于实现类。

如何使用开闭原则:(1)通过接口或者抽象类约束扩展,在抽象中的方法应该都是public的;参数类型引用对象应尽量的使用接口或者抽象类而不是具体的类;一旦抽象层确定后就尽量的保持稳定,不要修改(2)不应该有两个不同的变化出现在同一个接口或者抽象类中。

类必须做到低内聚高耦合。


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐