工作到现在差不多一年事件了,代码也写了好多了。代码写的多了自然就有新的问题了,回过头来看看自己之前写的代码,越看越感觉难看,对比github上别人的代码就感觉跟西施与如花之间的差距一样。所以就准备好好学习一下设计模式,好让自己的代码写出花来。
其实设计模式本质就是基于开闭原则、里氏替换原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特法则以及合成复用原则等面向对象原则总结出来的一些经验。
下面是我在学习过程中的一些笔记,看看就行了,不要太关注细节,毕竟我也是菜鸟。如果想学还是看一些书籍,至于什么书,首推肯定是GOF《设计模式-可复用面向对象软件的基础》,其次就是《设计模式之禅》。
设计模式(DesignPatterns)
概述
解决问题的一系列套路。提高代码的可用性,代码可读性以及代码的可靠性。
设计模式的意义
提高程序员的思维能力,编程能力和设计能力。
使程序设计更加标准化、代码编制更加工程化,大大提高软件的开发效率,从而缩短软件的开发周期。
使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
设计模式的基本要素
模式名称:命名,方便记忆。根据模式的问题、特点、解决方案、效果来命名。
问题:模式的应用环境。
解决方案:包括设计的组成成分、相互关系以及各自的职责和协作方式。
效果:模式的优缺点。
GOF23中设计模式的功能
单例模式(Singleton):该类只能有一个实例。
原型模式(Prototype):将一个类作为原型,通过对其进行复制而克隆出多个与原型类似的新实例。
工厂方法模式(FactoryMothod):定义一个创建产品的接口,由其子类决定生产什么产品。
抽象工厂模式(AbstractFactory):提供一个创建产品组的接口,由其子类决定生产一系列相关的产品。
建造者模式(Builder):将一个复杂对象分解成多个相对简单的部分,然后根据不同需要创建他们,最后组成该复杂对象。
代理模式(Proxy):为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接的访问该对象,从而限制、增强和修改该对象的一些特征。
适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口,是的原本由于接口不兼容而不能一起工作的哪些类能一起工作。
桥接模式(Bridge):将抽象与实现分离,使它们可以独立变化。它是通过组合关系来代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
装饰模式(Decorator):动态的给对象增加一些职责,即增加器额外功能。
外观模式(Facade):为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
享元模式(Flyweight):运用共享技术来有效的支持大量细粒度对象的复用。
组合模式(Composite):将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
模板方法模式(TemplateMethod):定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
策略模式(Strategy):定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的用户。
命令模式(Command):将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
责任链模式(Chain of Responsibility):把请求从链中的一个对象传到下一个对象,直到请求被响应,通过这种方法去除对象之间的耦合。
状态模式(State):允许一个对象在其内部状态发生改变时改变其行为能力。
观察者模式(Observer):多个对象间存在一对多关系,当一个对象发生改变时,将这种改变通知给其他多个对象,从而影响其他对象的行为。
中介者模式(Mediator):定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象间不必相互了解。
迭代器模式(Iterator):提供一种方法来顺序访问聚合对象中的一些列数据,而不暴露聚合对象的内部表示。
访问者模式(Visitor):在不改变集合元素的前提下,为下一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
备忘录模式(Memento):在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复他。
解释器模式(Interpreter):提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
面向对象设计原则
开闭原则
对扩展开放,对修改关闭
“抽象约束,封装变化”——用接口或者抽象类为软件实体定义一个相对稳定的抽象层,将相同的可变因素封装到具体的实现类中。
里氏替换原则
继承必须确保超类拥有的特性在子类中依然成立。
子类可以扩展父类的功能,但不能改变父类原有的功能。即子类继承父类时,除了添加新的方法外,尽量不要重写父类原有的方法,以防止程序运行过程中可能出现的问题。
里氏替换是实现开闭原则的重要方式之一。
克服可继承中重写继承方法造成可复用性差的缺点。
它是动作正确性的保证,即类的扩展不会给已有的系统引入新的错误,降低代码出错的可能性。
依赖倒置原则
高层模块不能依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
每个类尽量提供接口或者抽象类,或者两者兼备。
变量的声明类型尽量使接口或者抽象类。
任何类都不应该从具体类派生。
使用继承时尽量遵循里氏替换原则。
依赖倒置可以降低类间的耦合性。
依赖导致可以提高系统的稳定性。
依赖导致可以减少并行开发引起的风险。
依赖倒置可以提高代码的可读性和可依赖型。
单一职责原则
一个类应该有且仅有一个引起他变化的原因,否则类应该被拆分。
如果一个类承担了太多职责,一个职责发生变化时会削弱或者抑制其他职责的能力,而且当客户端需要对象的某一个职责时,不得不将其他不需要的职责全部包含进来
降低类的复杂度
提高类的可读性
提高系统的可维护性
变更引起的风险降低
接口隔离原则
客户端不应该被迫依赖他不使用的方法。
一个类对另一个类的依赖应该建立在最小的接口上。
将臃肿庞大的接口分解为多个粒度的小接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
如果接口粒度定义合理,能够保证系统的稳定性,但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义过多,则会降低灵活性,无法提供定制服务,给增提项目带来无法预料的风险。
使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
能够减少项目工程中的代码冗余。
接口尽量小,但要有限度,一个接口只服务于一个子模块或业务逻辑模块。
为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法
根据不同环境拆分接口
提高内聚,减少对外交互,使接口用最少的方法去完成最多的事情。
迪米特法则
如果两个软件实体无须直接通信,那么就不应当发生直接调用,可以通过第三方转发调用,其目的是降低类之间的耦合度,提高模块的相对独立性。
降低类之间的耦合性,提高模块的相互独立性。
由于亲和度降低,,从而提高的类的可复用率和系统的扩展性。
合成复用原则
软件复用时,尽量先使用组合或者聚合等关联关系来实现,其次才考虑继承关系实现。
采用组合或者聚合复用时:
维持了类的封装性。
新旧类之间的耦合度低。
复用的灵活性高。
继承复用破环了类的封装性。
继承中子类与父类耦合度高。
继承限制了复用的灵活性。
0条评论
点击登录参与评论