- 1、六大设计原则(面向对象设计原则)-概念
- 2、设计模式-概念
- 3、设计模式-概念-汇总
- 4、设计模式-概说
- 4-1:设计模式概说-单例模式
- 4-2:设计模式概说-工厂方法模式
- 4-3:设计模式概说-抽象工厂模式
- 4-4:设计模式概说-建造者模式
- 4-5:设计模式概说-原型模式
- 4-6:设计模式概说-适配器模式
- 4-7:设计模式概说-桥接模式
- 4-8:设计模式概说-组合模式
- 4-9:设计模式概说-装饰器模式
- 4-10:设计模式概说-外观模式
- 4-11:设计模式概说-享元模式
- 4-12:设计模式概说-代理模式
- 4-13:设计模式概说-访问者模式
- ">
- 4-14:设计模式概说-策略模式
- 4-15:设计模式概说-模板方法模式
- 4-16:设计模式概说-状态模式
- 4-17:设计模式概说-观察者模式
- 4-18:设计模式概说-备忘录模式
- 4-19:设计模式概说-中介者模式
- 4-20:设计模式概说-迭代器模式
- 4-21:设计模式概说-解释器模式
- 4-22:设计模式概说-命令模式
- 4-23:设计模式概说-责任链模式
Java设计模式
学习资料:https://www.pdai.tech/md/dev-spec/pattern/1_overview.html
1、六大设计原则(面向对象设计原则)-概念
1) 单一职责原则
一个类应该只负责一项职责,或者一个类中在方法足够少时,那么在方法级别上,保持单一职责原则。
2) 接口隔离原则
一个类对另一个类的依赖应该建立在最小的接口上。
3) 依赖倒转原则
面向接口编程,
高层模块不应该依赖低层模块,都应该依赖其抽象
细节(具体的实现类)应该依赖抽象(接口或抽象类)
依赖关系三种传递方式:
接口传递(依赖)
构造方法传递(依赖)
setter方式传递(聚合)
4) 里氏替换原则
使用继承时,在子类中尽量不要重写父类的方法,在适当的情况下,可以通过聚合,组合,依赖来解决问题。
5) 开闭原则 ocp
类、模块、函数对扩展开放,对修改关闭
6) 迪米特法则
一个对象应该对其他对象保持最少的了解(最少知道原则)。
一个类对自己依赖的类知道的越少越好
7) 合成复用原则
尽量使用组合/聚合的方式,而不是使用继承。
针对接口编程,而不是针对实现编程。
8)、设计原则总结:
8-1、开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;
8-2、里氏替换原则告诉我们不要破坏继承体系;
8-3、依赖倒置原则告诉我们要面向接口编程;
8-4、单一职责原则告诉我们实现类要职责单一;
8-5、接口隔离原则告诉我们在设计接口的时候要精简单一;
8-6、迪米特法则告诉我们要降低耦合度;
8-7、合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。
9)、前5个原则组合称为(单一、开闭、里氏替换、依赖倒置、接口隔离):SOLID 固定原则
1-1、六大设计原则-单一职责原则
1、概念:
1-1、单一职责原则(Single Responsibility Principle,SRP):又称单一功能原则。
1-2、职责指的是类变化的原因,即规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
1-3、核心是控制类的粒度大小、将对象解耦、提高其内聚性。
1-4、因为有职责扩散。所谓职责扩散,就是因为某种原因,职责P被分化为粒度更细的职责P1和P2。
1-5、在职责扩散到我们无法控制的程度之前,立刻对代码进行重构。
2、优点:
2-1、降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
2-2、提高类的可读性。复杂性降低,自然其可读性会提高。
2-3、提高系统的可维护性。可读性提高,那自然更容易维护了。
2-4、变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。
3、实现方法:
3-1、按照类的不同职责并将其分离,再封装到不同的类或模块中。
4、应用扩展性:
4-1、单一职责同样也适用于方法。一个方法应该尽可能做好一件事情。
1-2、六大设计原则-里氏替换原则
1、概念:
1-1、里氏替换原则(Liskov Substitution Principle,LSP)。
1-2、继承复用的基础,它反映了基类与子类之间的关系。
1-3、是对开闭原则的补充,是对实现抽象化的具体步骤的规范。
2、优点:
2-1、里氏替换原则是实现开闭原则的重要方式之一。
2-2、它克服了继承中重写父类造成的可复用性变差的缺点。
2-3、它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
2-4、加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。
3、实现方法:
3-1、子类可以扩展父类的功能,但不能改变父类原有的功能。
3-2、子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。也尽量不要重载父类A的方法。
3-3、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
3-4、子类中可以增加自己特有的方法。
4、应用扩展性:
1-3、六大设计原则-依赖倒置/倒转原则
1、概念:
1-1、依赖倒置原则(Dependence Inversion Principle,DIP)。
1-2、其核心思想是:要面向接口编程,不要面向实现编程。[要依赖于抽象,不依赖于具体。]
1-3、高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
1-4、是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
2、优点:
2-1、依赖倒置原则可以降低类间的耦合性。
2-2、依赖倒置原则可以提高系统的稳定性。
2-3、依赖倒置原则可以减少并行开发引起的风险。
2-4、依赖倒置原则可以提高代码的可读性和可维护性。
3、实现方法:
3-1、通过要面向接口的编程来降低类间的耦合性。
3-2、使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。
4、应用扩展性:
1-3-1、依赖倒置/倒转原则-举例
1、Spring中BeanFactoryPostProcessor接口(BeanDefinition的后置处理器)#postProcessBeanFactory()方法参数:ConfigurableListableBeanFactory 的最终实现类只有 DefaultListableBeanFactory ,这里的入参也是接口。
1-4、六大设计原则-接口隔离原则
1、概念:
1-1、接口隔离原则(Interface Segregation Principle,ISP)。
1-2、要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
1-3、建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
1-4、接口隔离原则和单一职责原则比较:
1-4-1、都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想。
1-4-2、单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
1-4-3、单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。
2、优点:
2-1、接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
2-2、能减少项目工程中的代码冗余。
2-3、将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
3、实现方法:
3-1、接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
3-2、为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
3-3、了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同深入了解业务逻辑。
3-4、提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
4、应用扩展性:
4-1、运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。
1-5、六大设计原则-迪米特法则
1、概念:
1-1、迪米特法则(Law of Demeter,LoD),又称最少知识原则(Least Knowledge Principle,LKP)
1-2、一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
1-3、一个软件实体应当尽可能少的与其他实体发生相互作用。
1-4、一个对象应该对其他对象保持最少的了解。
1-5、这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。
2、优点:
2-1、降低了类之间的耦合度,提高了模块的相对独立性。
2-2、由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
3、实现方法:
3-1、尽量降低类与类之间的耦合。
3-2、对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法不对外泄漏任何信息。
3-3、从依赖者的角度来说,只依赖应该依赖的对象。
3-4、从被依赖者的角度说,只暴露应该暴露的方法。
4、应用扩展性:
4-1、在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
4-2、不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
4-3、谨慎使用序列化(Serializable)功能。[???]
1-6、六大设计原则-开闭原则
1、概念:
1-1、开闭原则(Open Closed Principle,OCP),强调:软件实体[划分的模块、类与接口、方法]应当对扩展开放,对修改关闭。
1-2、当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。
2、优点:
2-1、对软件测试的影响:软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了
2-2、可以提高代码的可复用性。
2-3、可以提高软件的可维护性。
3、实现方法:
3-1、"抽象约束、封装变化: 通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。
3-2、当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
4、应用扩展性:
1-7、六大设计原则[面向对象设计原则]-合成复用原则
1、概念:
1-1、合成复用原则(Composite Reuse Principle,CRP),又称组合/聚合复用原则(CARP)。
1-2、要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
1-3、合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
2、优点:
2-1、维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
2-2、新对象可以动态地引用与成分对象类型相同的对象。
2-3、新旧类之间的耦合度低,新对象存取成分对象的唯一方法是通过成分对象的接口。
3、缺点:通常类的复用分为继承复用和合成复用两种
3-1、继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
3-2、子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
3-3、从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。
4、实现方法:
4-1、通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。
5、应用扩展性:
2、设计模式-概念
1、设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
2、作用:可重用代码、让代码更容易被他人理解、保证代码可靠性。
3、分类:总共23种
3-1、创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
3-2、结构型模式:把类或对象结合在一起形成一个更大的结构。
3-3、行为型模式:类和对象如何交互,及划分责任和算法。
3-4、具体:
创建型模式有:
单例模式、工厂方式模式、抽象工厂模式、建造者模式、原型模式、
结构型模式有:
适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式
行为型模式有:
访问者模式、策略模式、模板模式、状态模式、观察者模式、备忘录模式、中介者模式、迭代器模式、解释器模式、命令模式、责任链模式、
4、参考链接:
https://www.cnblogs.com/pony1223/p/7608955.html
http://c.biancheng.net/view/1333.html
https://www.cnblogs.com/pony1223/p/7608955.html
2-1、设计模式-种类划分示意图
3、设计模式-概念-汇总
单例模式:某个类只能有一个实例,提供一个全局的访问点。
简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。
抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。
组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。
装饰模式:动态的给对象添加新的功能。
代理模式:为其他对象提供一个代理以便控制这个对象的访问。
亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
观察者模式:对象间的一对多的依赖关系。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
中介者模式:用一个中介对象来封装一系列的对象交互。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
4、设计模式-概说
4-1:设计模式概说-单例模式
1、定义:
1-1、单例模式(Singleton),指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
2、特点:
2-1、单例类只有一个实例对象。
2-2、该单例对象必须由单例类自行创建。
2-3、单例类对外提供一个访问该单例的全局访问点。
3、优点:
3-1、单例模式可以保证内存里只有一个实例,减少了内存的开销。
3-2、单例模式设置全局访问点,可以优化和共享资源的访问。
3-3、可以避免对资源的多重占用。
4、缺点:
4-1、单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。
4-2、单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
4-3、在并发测试中,单例模式不利于代码调试。
5、应用场景:
5-1、需要频繁创建的一些类。
5-2、某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
5-3、频繁访问数据库或文件的对象。
5-4、[???]当对象需要被共享的场合,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
6、模式的结构
6-1、单例模式的主要角色如下:
单例类:包含一个实例且能自行创建这个实例的类。
访问类:使用单例的类。
6-2、单例模式实现方式:两种[饿汉式单例][懒汉式单例]
7、扩展:
单例模式可扩展为有限的多例(Multitcm)模式,这种模式可生成有限个实例并保存在 ArrayList 中,客户需要时可随机获取
4-1-1:设计模式概说-单例模式-结构示意图
4-1-2:设计模式概说-单例模式-扩展结构示意图
4-2:设计模式概说-工厂方法模式
1、定义:
1-1、是对简单工厂模式的进一步抽象化,来满足开闭原则。
2、特点:
2-1、满足“开闭原则”的前提下,客户随意增删或改变对软件相关对象的使用。
2-2、工厂方法模式只生产一个等级的产品。
3、优点:
3-1、用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
3-2、对于新产品的创建,只需多写一个相应的工厂类。
3-3、典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类。
4、缺点:
4-1、类的个数容易过多,增加复杂度。
4-2、增加了系统的抽象性和理解难度。
4-3、抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
5、应用场景:
5-1、
6、模式的结构:
6-1、工厂方法模式的主要角色如下。
抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct()来创建产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应[!!!]。
7、模式的应用举例:
7-1、设计畜牧场,分析:有很多种类的畜牧场,如养马场用于养马,养牛场用于养牛。
4-2-1、设计模式概说-工厂方法模式-结构图
4-3:设计模式概说-抽象工厂模式
1、定义:
1-1、抽象工厂模式(AbstractFactory)将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族。
1-2、是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
1-3、
2、特点:
2-1、抽象工厂模式可生产多个等级的产品。
2-2、系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
2-3、系统一次只可能消费其中某一族产品,即同族的产品一起使用。
3、优点:
3-1、当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
3-2、抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。
4、缺点:
4-1、当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。
5、应用场景:
5-1、
6、模式的结构:
6-1、工厂方法模式的主要角色如下。
抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间多对一关系[!!!]。
7、模式的适用场景:
7-1、当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
7-2、系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
7-3、系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
8、模式的应用举例:
8-1、用抽象工厂模式设计农场类。
4-3-1:设计模式概说-抽象工厂模式-结构图
4-4:设计模式概说-建造者模式
1、定义:
1-1、建造者模式(Builder),将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。
1-2、将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。
2、特点:
2-1、建造者模式注重零部件的组装过程,而工厂方法模式注重零部件的创建过程。
3、优点:
3-1、扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
3-2、客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
4、缺点:
4-1、产品的组成部分必须相同,这限制了其使用范围。
4-2、如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
5、应用场景:
5-1、
6、模式的结构:
6-1、产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
6-2、抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
6-3、具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
6-4、指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
7、模式的适用场景:
7-1、如果创建复杂对象,就可以考虑使用建造者模式。
7-2、相同的方法,不同的执行顺序,产生不同的结果。
7-3、多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
7-4、产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
7-5、初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
8、模式的应用举例:
9、建造者模式与工厂方法模式的比较:
9-1、建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
9-2、创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
9-3、关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
9-4、建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。
4-4-1:设计模式概说-建造者模式-结构图
4-5:设计模式概说-原型模式
1、定义:
1-1、原型(Prototype)模式,用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
2、特点:
3、优点:
3-1、Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
3-2、可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
4、缺点:
4-1、需要为每一个类都配置一个 clone 方法,clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
4-2、而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。
5、应用场景:
6、模式的结构: Java 提供了对象的 clone() 方法
6-1、抽象原型类:规定了具体原型对象必须实现的接口。
6-2、具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
6-3、访问类:使用具体原型类中的 clone() 方法来复制新的对象。
7、模式的实现:原型模式的克隆分为浅克隆和深克隆。
7-1、浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
7-2、深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
7-3、Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆。
7、模式的适用场景:
8、模式的应用举例:
8-1、用原型模式模拟“孙悟空”复制自己:孙悟空拔下猴毛轻轻一吹就变出很多孙悟空。
8-2、用原型模式生成“三好学生”奖状:同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,属于相似对象的复制。
4-5-1:设计模式概说-原型模式-结构图
4-6:设计模式概说-适配器模式
1、定义:
1-1、适配器模式(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
2、特点:
2-1、适配器模式分为类结构型模式和对象结构型模式[常用]两种
3、优点:
3-1、客户端通过适配器可以透明地调用目标接口。
3-2、复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
3-3、将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
4、缺点:
4-1、增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
5、应用场景:
5-1、
6、模式的结构:
6-1、类适配器模式可采用多重继承方式实现,对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。
6-2、主要角色。:
6-2-1、目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
6-2-2、适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
6-2-3、适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
7、模式的适用场景:
8、模式的应用举例:
8-1、用适配器模式(Adapter)模拟新能源汽车的发动机:新能源汽车的发动机有电能发动机(Electric Motor)和光能发动机(Optical Motor)等,各种发动机的驱动方法不同。
9、模式的扩展:
9-1、适配器模式(Adapter)可扩展为双向适配器模式,双向适配器类既可以把适配者接口转换成目标接口,也可以把目标接口转换成适配者接口。
4-6-1:设计模式概说-类适配器模式-结构图
4-6-2:设计模式概说-对象适配器模式-结构图
4-7:设计模式概说-桥接模式
1、定义:
1-1、桥接模式(Bridge): 将抽象与实现分离,取消二者的继承关系,改用组合关系,使它们可以独立变化。
2、特点:
2-1、用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
2-2、符合开闭原则,符合合成复用原则。
3、优点:
3-1、抽象与实现分离,扩展能力强。
3-2、其实现细节对客户透明
4、缺点:
4-1、由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,增加了系统的理解与设计难度。
5、应用场景:
5-1、
6、模式的结构:
6-1、主要角色:
6-1-1、抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
6-1-2、扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
6-1-3、实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
6-1-4、具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
7、模式的适用场景:用组合/聚合方式去替换继承[!!!]
7-1、当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
7-2、当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
7-3、当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
8、模式的应用举例:
8-1、用桥接(Bridge)模式模拟女士皮包的选购。
分析:女士皮包有很多种,可以按用途分、按皮质分、按品牌分、按颜色分、按大小分等,存在多个维度的变化。
9、模式的扩展:
9-1、桥接模式可与适配器模式联合使用,当桥接模式的实现化角色的接口与现有类的接口不一致时,可以在二者中间定义一个适配器将二者连接起来。
4-7-1:设计模式概说-桥接模式-结构图
4-8:设计模式概说-组合模式
1、定义:
1-1、组合(Composite Pattern)模式:是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性。
2、特点:
2-1、用来描述整体与部分的关系,它将对象组织到树形结构中。
2-2、根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用。
2-3、叶子节点与树枝节点在语义上不属于用一种类型,用组合模式,把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。
3、优点:
3-1、使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
3-2、在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
4、缺点:
4-1、设计较复杂,客户端需要花更多时间理清类之间的层次关系;
4-2、不容易限制容器中的构件;
5、应用场景:
5-1、
6、模式的结构: 组合模式分为透明式的组合模式和安全式的组合模式。
6-1、主要角色。
6-1-1、抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
6-1-2、树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
6-1-3、树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
6-2、透明式的组合模式:在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。
6-3、在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,避免了安全问题,但失去了透明性。
7、模式的适用场景:
7-1、在需要表示一个对象整体与部分的层次结构的场合。
7-2、要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
8、模式的应用举例:
8-1、用组合模式实现当用户在商店购物后,显示其所选商品信息,并计算所选商品总价的功能。
8-2、
9、模式的扩展:
4-8-1:设计模式概说-透明式组合模式-结构图
4-8-2:设计模式概说-安全式组合模式-结构图
4-9:设计模式概说-装饰器模式
1、定义:
1-1、装饰模式(Decorator),指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。它属于对象结构型模式。
2、特点:
2-1、如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能。
3、优点:
3-1、装饰器是继承的有力补充,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用。
3-2、通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
4、缺点:
4-1、装饰模式会增加许多子类,过度使用会增加程序得复杂性。
5、应用场景:
5-1、
6、模式的结构:
6-1、主要角色:
6-1-1、抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
6-1-2、具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
6-1-3、抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
6-1-4、具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
7、模式的适用场景:
7-1、当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
7-2、当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
7-3、当对象的功能要求可以动态地添加,也可以再动态地撤销时。
8、模式的应用举例:
8-1、用装饰模式实现游戏角色“莫莉卡·安斯兰”的变身。
8-2、装饰模式在 Java 语言中的最著名的应用莫过于 Java I/O 标准库的设计了。
9、模式的扩展:
9-1、如果只有一个具体构件而没有抽象构件时,可以让抽象装饰继承具体构件。
9-2、如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并。
4-9-1:设计模式概说-装饰器模式-结构图
4-10:设计模式概说-外观模式
1、定义:
1-1、外观模式(Facade),又称门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
1-2、该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节。
2、特点:
2-1、外观(Facade)模式是“迪米特法则”的典型应用
3、优点:
3-1、降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
3-2、降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象。
4、缺点:
4-1、增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。
5、应用场景:
5-1、
6、模式的结构:
6-1、主要角色:
6-1-1、外观(Facade)角色:为多个子系统对外提供一个共同的接口。
6-1-2、子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
6-1-3、客户(Client)角色:通过一个外观角色访问各个子系统的功能。
6-2、主要是定义了一个高层接口。它包含了对各个子系统的引用,客户端可以通过它访问各个子系统的功能。
7、模式的适用场景:
7-1、对分层结构系统构建时,使用外观模式定义子系统中每层的入口点。
7-2、子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。
7-3、当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离。
8、模式的应用举例:
8-1、用“外观模式”设计一个婺源特产的选购界面。
9、模式的扩展:
9-1、在外观模式中,当增加或移除子系统时需要修改外观类,这违背了“开闭原则”。如果引入抽象外观类,则在一定程度上解决了该问题。
4-10-1:设计模式概说-外观模式-结构图
4-11:设计模式概说-享元模式
1、定义:
1-1、享元模式(Flyweight),运用共享技术来有效地支持大量细粒度对象的复用。
1-2、享元模式的本质是缓存共享对象,降低内存消耗。提出了两个要求,细粒度和共享对象。
1-3、将这些对象的信息分为两个部分:内部状态和外部状态。
1-3-1、内部状态指对象共享出来的信息,存储在享元信息内部,并且不回随环境的改变而改变;
1-3-2、外部状态指对象得以依赖的一个标记,随环境的改变而改变,不可共享。
2、特点:
2-1、通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
2-2、享元模式同样要求创建一个或一组对象,并且就是通过工厂方法模式生成对象的,只不过享元模式为工厂方法模式增加了缓存这一功能。
3、优点:
3-1、相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
4、缺点:
4-1、读取享元模式的外部状态会使得运行时间稍微变长。
5、应用场景:
5-1、
6、模式的结构:
6-1、主要角色:
6-1-1、抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
6-1-2、具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
6-1-3、非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
6-1-4、享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
7、模式的适用场景:
7-1、当系统中多处需要同一组信息时,可以把这些信息封装到一个对象中,然后对该对象进行缓存。
7-2、由于享元模式需要额外维护一个保存享元的数据结构,所以应当在有足够多的享元实例时才值得使用享元模式。
8、模式的应用举例:
8-1、享元模式在五子棋游戏中的应用。
9、模式的扩展:
4-11-1:设计模式概说-享元模式-结构图
4-12:设计模式概说-代理模式
1、定义:
1-1、代理模式:需要给某对象提供一个代理以控制对该对象的访问。
2、特点:
2-1、访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
2-2、使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。
3、优点:
3-1、代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
3-2、代理对象可以扩展目标对象的功能;
4、缺点:[使用动态代理方式解决]
4-1、在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢
5、应用场景:
5-1、代理模式分为静态代理和动态代理。
5-1-1、静态:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
5-1-2、动态:在程序运行时,运用反射机制动态创建而成。
6、模式的结构:
6-1、通过定义一个继承抽象主题的代理来包含真实主题,从而实现对真实主题的访问。
6-2、主要角色:
6-2-1、抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
6-2-2、真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
6-2-3、代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
7、模式的适用场景:
7-1、当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访问。
8、模式的应用举例:
8-1、韶关“天街e角”公司是一家婺源特产公司的代理公司。
9、模式的扩展:
9-1、采用动态代理模式解决真实主题与代理主题一一对应,增加真实主题也要增加代理的问题。
4-12-1:设计模式概说-代理模式-结构图
4-13:设计模式概说-访问者模式
1、定义:
1-1、访问者模式(Visitor),将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。
2、特点:
2-1、将对数据的操作与数据结构进行分离,是对象行为类模式中最复杂的一种模式。
3、优点:
3-1、扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
3-2、复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
3-3、灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
3-4、符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。
4、缺点:
4-1、增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
4-2、破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
4-3、违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。
5、应用场景:
5-1、如何将作用于元素的操作分离出来封装成独立的类?
6、模式的结构:
6-1、主要角色。
6-1-1、抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
6-1-2、具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
6-1-3、抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
6-1-4、具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
6-1-5、对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
7、模式的适用场景:
7-1、当系统中存在类型数量稳定(固定)的一类数据结构时,可以使用访问者模式方便地实现对该类型所有数据结构的不同操作,而又不会对数据产生任何副作用(脏数据)。
7-2、当对集合中的不同类型数据(类型数量稳定)进行多种操作时,使用访问者模式。
7-3、对象结构相对稳定,但其操作算法经常变化的程序。
7-4、对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。
7-5、对象结构包含很多类型的对象,希望对这些对象实施一些依赖于其具体类型的操作。
8、模式的应用举例:
8-1、利用“访问者(Visitor)模式”模拟艺术公司与造币公司的功能。
9、模式的扩展:
9-1、与迭代器模式联用。因为访问者模式中的“对象结构”是一个包含元素角色的容器,当访问者遍历容器中的所有元素时,常常要用迭代器。
9-2、访问者(Visitor)模式同“组合模式”联用。因为访问者(Visitor)模式中的“元素对象”可能是叶子对象或者是容器对象,如果元素对象包含容器对象,就必须用到组合模式。
4-13-1:设计模式概说-访问者模式-结构图
4-14:设计模式概说-策略模式
1、定义:
1-1、策略模式(Strategy),该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
1-2、准备一组算法,并将这组算法封装到一系列的策略类里面,作为一个抽象策略类的子类。
1-3、策略模式属于对象行为模式。
2、特点:
2-1、它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
3、优点:
3-1、多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if...else 语句、switch...case 语句。
3-2、策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
3-3、策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
3-4、策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
3-5、策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
4、缺点:
4-1、客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
4-2、策略模式造成很多的策略类,增加维护难度。
5、应用场景:
5-1、
6、模式的结构:
7、模式的适用场景:
7-1、多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。
8、模式的应用举例:
8-1、策略模式在“大闸蟹”做菜中的应用。
分析:关于大闸蟹的做法有很多种,我们以清蒸大闸蟹和红烧大闸蟹两种方法为例,介绍策略模式的应用。
8-2、 Java SE 中的容器布局管理就是一个典型的实例,Java SE 中的每个容器都存在多种布局供用户选择。
9、模式的扩展:
9-1、在一个使用策略模式的系统中,当存在的策略很多时,客户端管理所有策略算法将变得很复杂,如果在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度。
4-14-1:设计模式概说-策略模式-结构图
4-15:设计模式概说-模板方法模式
1、定义:
1-1、模板方法模式(Template Method):定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
2、特点:
2-1、需要注意抽象类与具体子类之间的协作。它用到了虚函数的多态性技术以及“不用调用我,让我来调用你”的反向控制技术。
3、优点:
3-1、它封装了不变部分,扩展可变部分。
3-2、它在父类中提取了公共的部分代码,便于代码复用。
3-3、部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
4、缺点:
4-1、父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
4-2、由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。
5、应用场景:
6、模式的结构:
6-1、抽象类/抽象模板(Abstract Class): 负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。
6-2、具体子类/具体实现(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
7、模式的适用场景:
7-1、算法的整体步骤很固定,但其中个别部分易变时。
7-2、当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。
7-3、当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。
8、模式的应用举例:
8-1、在模板方法模式中,基本方法包含:抽象方法、具体方法和钩子方法,正确使用“钩子方法”可以使得子类控制父类的行为
4-15-1:设计模式概说-模版方法模式-结构图
4-16:设计模式概说-状态模式
1、定义:
1-1、状态(State)模式的定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
2、特点:
2-1、状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
3、优点:
3-1、将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
3-2、通过定义新的子类很容易地增加新的状态和转换。
4、缺点:
4-1、状态模式的使用必然会增加系统的类与对象的个数。
4-2、状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
5、应用场景:
6、模式的结构:
6-1、主要角色。
6-1-1、环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
6-1-2、抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
6-1-3、具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
8、模式的实现:
8-1、
9、模式的适用场景:9-1、
9-1、当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
9-2、一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。
10、模式的扩展:
10-1、在有些情况下,可能有多个环境对象需要共享一组状态,这时需要引入享元模式,将这些具体状态对象放在集合中供程序共享。
4-16-1:设计模式概说-状态模式-结构图
4-17:设计模式概说-观察者模式
1、定义:
1-1、观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
1-2、这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
2、特点:
2-1、实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来
3、优点:
3-1、降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
3-2、目标与观察者之间建立了一套触发机制。
4、缺点:
4-1、标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
4-2、观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
5、应用场景:
5-1、在软件系统中,当系统一方行为依赖另一方行为的变动时,可使用观察者模式松耦合联动双方,使得一方的变动可以通知到感兴趣的另一方对象,从而让另一方对象对此做出响应。
5-2、对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
5-3、当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
5-4、实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
5-5、多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知。
6、模式的结构:
6-1、主要角色如下。
6-1-1、抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
6-1-2、具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
6-1-3、抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
6-1-4、具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
8、模式的实现:
8-1、
9、模式的扩展:
9-1、在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例。
4-17-1:设计模式概说-观察者模式-结构图
4-18:设计模式概说-备忘录模式
1、定义:
1-1、备忘录模式(Memento)的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。
1-2、该模式又叫快照模式。
2、特点:
2-1、
3、优点:
3-1、提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
3-2、实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
4、缺点:
4-1、资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
5、应用场景:
5-1、需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
5-2、需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。
6、模式的结构:
6-1、主要角色如下。
6-1-1、发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
6-1-2、备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
6-1-3、管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
7、模式的实现:
7-1、备忘录模式的核心是设计备忘录类以及用于管理备忘录的管理者类
8、模式的扩展:
4-18-1:设计模式概说-备忘录模式-结构图
4-19:设计模式概说-中介者模式
1、定义:
1-1、中介者模式(Mediator)的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。
1-2、中介者模式又叫调停模式,它是迪米特法则的典型应用。
2、特点:
2-1、中介者模式是一种对象行为型模式。
3、优点:
3-1、降低了对象之间的耦合性,使得对象易于独立地被复用。
3-2、将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
4、缺点:
4-1、将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。
5、应用场景:
5-1、当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
5-2、当想创建一个运行于多个类之间的对象,又不想生成新的子类时。
6、模式的结构:
6-1、主要角:
6-1-1、抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
6-1-2、具体中介者(Concrete Mediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
6-1-3、抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
6-1-4、具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
7、模式的实现:
7-1、
8、模式的扩展:
8-1、不定义中介者接口,把具体中介者对象实现成为单例。
8-2、同事对象不持有中介者,而是在需要的时候直接获取中介者对象并调用。
4-19-1:设计模式概说-中介者模式-结构图
4-20:设计模式概说-迭代器模式
1、定义:
1-1、迭代器模式(Iterator)的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
1-2、通过将聚合对象的遍历行为分离出来,抽象成迭代器类来实现的,其目的是在不暴露聚合对象的内部结构的情况下,让外部代码透明地访问聚合的内部数据。
2、特点:
2-1、它在客户访问类与聚合类之间插入一个迭代器,这分离了聚合对象与其遍历行为,对客户也隐藏了其内部细节。
2-2、在日常开发中,我们几乎不会自己写迭代器。除非需要定制一个自己实现的数据结构对应的迭代器,否则,开源框架提供的 API 完全够用。
3、优点:
3-1、支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
3-2、增加新的聚合类和迭代器类都很方便,无须修改原有代码。
3-3、封装性良好,为遍历不同的聚合结构提供一个统一的接口。
4、缺点:
4-1、增加了类的个数,这在一定程度上增加了系统的复杂性。
4-2、
5、应用场景:
5-1、当需要为聚合对象提供多种遍历方式时。
5-2、当需要为遍历不同的聚合结构提供一个统一的接口时。
5-3、当访问一个聚合对象的内容而无须暴露其内部细节的表示时。
6、模式的结构:
6-1、主要角色:
6-1-1、抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
6-1-2、具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
6-1-3、抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
6-1-4、具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
7、模式的实现:
7-1、
8、模式的扩展:
8-1、迭代器模式常常与组合模式结合起来使用,在对组合模式中的容器构件进行访问时,经常将迭代器潜藏在组合模式的容器构成类中。
4-20-1:设计模式概说-迭代器模式-结构图
4-21:设计模式概说-解释器模式
1、定义:
1-1、解释器模式(Interpreter)的定义:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。
2、特点:
2-1、用编译语言的方式来分析应用中的实例。
2-2、实现了文法表达式处理的接口,该接口解释一个特定的上下文。
3、优点:
3-1、扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
3-2、容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。
4、缺点:
4-1、执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。
4-2、会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。
5、应用场景:
5-1、当语言的文法较为简单,且执行效率不是关键问题时。
5-2、当问题重复出现,且可以用一种简单的语言来进行表达时。
5-3、当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释。
6、模式的结构:
6-1、主要角色:
6-1-1、抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
6-1-2、终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
6-1-3、非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
6-1-4、环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
6-1-5、客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。
7、模式的实现:
7-1、关键是定义文法规则、设计终结符类与非终结符类、画出结构图,必要时构建语法树,
8、模式的扩展:
8-1、
4-21-1:设计模式概说-解释器模式-结构图
4-22:设计模式概说-命令模式
1、定义:
1-1、命令模式(Command)的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
2、特点:
2-1、两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
3、优点:
3-1、通过引入中间件(抽象接口)降低系统的耦合度。
3-2、扩展性良好,增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,且满足“开闭原则”。
3-3、方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
4、缺点:
4-1、可能产生大量具体的命令类。因为每一个具体操作都需要设计一个具体命令类,这会增加系统的复杂性。
5、应用场景:
5-1、请求调用者需要与请求接收者解耦时,命令模式可以使调用者和接收者不直接交互。
5-2、系统随机请求命令或经常增加、删除命令时,命令模式可以方便地实现这些功能。
5-3、当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。
5-4、当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现。
6、模式的结构:
6-1、主要角色:
6-1-1、抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
6-1-2、具体命令类(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
6-1-3、实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
6-1-4、调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
7、模式的实现:
7-1、可以将系统中的相关操作抽象成命令,使调用者与实现者相关分离。
8、模式的扩展:
8-1、在软件开发中,有时将命令模式与前面学的组合模式联合使用,这就构成了宏命令模式,也叫组合命令模式。宏命令包含了一组命令,它充当了具体命令与调用者的双重角色,执行它时将递归调用它所包含的所有命令。
4-22-1:设计模式概说-命令模式-结构图
4-23:设计模式概说-责任链模式
1、定义:
1-1、责任链模式(Chain of Responsibility)的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
1-2、责任链模式也叫职责链模式。
2、特点:
2-1、在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。
3、优点:
3-1、降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
3-2、增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4、缺点:
4-1、不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
4-2、责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如:可能会造成循环调用。
5、应用场景:
5-1、多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
5-2、可动态指定一组对象处理请求,或添加新的处理者。
5-3、需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。
6、模式的结构:
6-1、主要角色:
6-1-1、抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
6-1-2、具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
6-1-3、客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
7、模式的实现:
7-1、可以通过数据链表来实现职责链模式的数据结构。
7-2、责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理。
8、模式的扩展:
8-1、纯的职责链模式:一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理。
8-2、不纯的职责链模式:允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收。
4-23-1:设计模式概说-责任链模式-结构图
http://c.biancheng.net/view/1378.html
https://www.cnblogs.com/pony1223/p/7608955.html