设计模式
七大设计原则 :
单一职责原则: Single Responsibility Principle 一个类只负责一项职责 SRP
里氏替换原则: Liskov Substitution Principle 所有引用基类的地方,必须能透明地使用其子类的对象 LSP
依赖倒置原则: Dependence Inversion Principle 子类型能够替换掉它们的父类型 DIP
接口隔离原则: Interface Segregation Principle 一个类对另一个类的依赖应该建立在最小的接口上 ISP
迪米特法则: Principle Of Least Knowledge 一个对象应对其他对象保持最少的了解 PLK
开闭原则: Open close Principle 对外扩展开放,对内修改关闭 OCP
合用复用原则: Composite/Aggregate Reuse Principle 尽量使用组合和聚合少用继承的关系来达到复用的原则 CARP
24种设计模式 :
1. 策略模式 Strategy Pattern
2. 代理模式 Proxy Pattern
3. 单例模式 Singleton Pattern
4. 多例模式 Multition Pattern
5. 工厂方法模式 Factory Method Pattern
6. 抽象工厂模式 Abstract Factory Pattern
7. 门面模式 Facade Pattern
8. 适配器模式 Adapter Pattern
9. 模板方法模式 Template Method Pattern
10. 建造者模式 Builder Pattern
11. 桥梁模式 Bridge Pattern
12. 命令模式 Command Pattern
13. 装饰模式 Decorator Pattern
14. 迭代器模式 Iterator Pattern
15. 组合模式 Composite Pattern
16. 观察者模式 Observer Pattern
17. 责任链模式 Chain Of Responsibility Pattern
18. 访问者模式 Visitor Pattern
19. 状态模式 State Pattern
20. 原型模式 Prototype Pattern
21. 中介者模式 Mediator Pattern
22. 解释器模式 Interpreter Pattern
23. 享元模式 Flyweight Pattern
24. 备忘录模式 Memento Pattern
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
什么是设计模式:
是一套被反复使用,多数人知晓的经过分类的、代码设计经验的总结。
使用设计模式的目的:
为了代码可重用性,让代码更容易被他人理解,保证代码可靠性。
单例模式 Singleton Pattern
有些对象,我们需要确保在一个程序中有且只能有一个。
单例模式 分为
懒汉模式
饿汉模式
实现 饿汉 模式 :
实现单例模式的步骤:
① 私有化类的构造方法。
② 提供静态成员并初始化来保存唯一的实例。
③ 提供静态获取成员的方法来获取实例。
饿汉模式:是在类被加载时,自动会创建单例实例对象。不管用户是否会去调用该成员。
实现 懒汉 模式:
实现单例模式的步骤:
私有化类的构造方法。
懒汉模式:是在类的方法第一次被调用时,会创建单例实例对象。后面再重复调用时,直接获取对象。
区别:
饿汉模式加载类时会比较慢,但运行时获取对象的速度会比较快。
懒汉模式加载类时会比较快,但运行时获取对象的速度会比较慢。
饿汉模式是线程安全的,懒汉模式线程不安全。
由于懒汉模式是非线程安全的,所以在多线程时,还是有可能创建多个实例对象,
故需要使用 线程锁,避免创建多个实例
工厂方法模式 Factory Method Pattern
实例化对象,用工厂代理new操作。
工厂模式的分类:
简单工厂模式
抽象工厂模式 抽象工厂 ——> 实体工厂 ——> 抽象产品 ——> 实体产品
定义一个接口来创建对象,但是让子类来决定哪些类需要实例化。
工厂方法把实例化的工作推迟到了子类中去实现。
调用者直接调用工厂,由工厂创建对象,调用者不需要知道工厂内部的实现机制。
延迟初始化。
代理模式 Proxy Pattern
代理模式的作用是什么?
为其他对象提供一种代理以控制对这个对象的访问。代理对象起到一个中介的作用,可去掉一些服务或者增加一些服务
应用场景:
远程代理: 为不同地址空间的服务器提供局域网代理。(翻墙,监控多个店铺的摄像头应用)
虚拟代理: 根据需要将一个资源消耗很大的对象进行延迟,真正需要时再进行创建。(网页中的图片或者视频异步加载)
保护代理: 增加一些权限,提供对原有对象的保护。(权限控制)
智能代理:提供目标对象额外的一些服务。(火车票代售点,中介)
代理实现的方式:
静态代理:已知代理类的情况下
代理和被代理的对象在代理之前是确定的,它们都是实现相同接口或者继承相同的类
继承方式:① 添加一个功能接口,提供一个功能方法 ② 使用目标类实现功能接口,实现功能方法
③ 使用代理类继承目标类并重写功能方法,使用 super.父类功能方法
包含/合成/聚合方式: ① 添加一个功能接口,提供一个功能方法 ②使用目标类,实现功能接口,并实现功能方法
③ 添加一个代理类,增加一个带参的构造方法,增加一个方法,使用目标类对象调用功能方法
两种实现方式的对比:
使用继承方式实现代理,代理类和被代理类耦合度较高,不便于扩展,每次增加新的代理都必须重新添加新的代理类。成本较高。
使用聚合方式实现代理,代理类和被代理类的耦合度较低,能方便的替换被代理类的对象。也更容易复用
在面向对象的基本原则中,也推荐我们多使用合成而不是继承,所以合成方式更适合代理模式
动态代理:
JDK 动态代理
① 添加一个功能接口,提供功能方法 ② 使用目标类,实现目标功能接口,并实现功能方法
③ 添加一个动态代理类,实现 InvocationHandler 接口,添加带有功能接口对象的构造方法,重写 InnovationHandler 中的 invoke 方法
Object obj = method.invoke(this.功能对象,args);
④ 获取功能接口对象,获取动态代理类对象
功能对象 = Proxy.newProxyInstance(代理类对象.getClass().getClassLoader(),被代理类对象.getClass().getInterfaces(),动态代理类对象);
功能对象 = Proxy.newProxyInstance(代理类对象.getClass().getClassLoader(),new Class[]{被代理类.class} ,动态代理类对象);
使用动态代理,必须实现 InvocationHandler 接口,InvocationHandler 接口位于 java.lang.reflect 包下
InvocationHandler 接口中只有一个方法:
Object invoke(Object proxy,Method method,Object[] args)
proxy : 被代理类的对象
method : 被代理类的方法
args : 被代理的方法的参数
调用动态代理,需要使用 Proxy.newProxyInstance()静态方法
Proxy.newProxyInstance(loader,interfaces,handler)
loader : 代理类类加载器
interfaces : 被代理类实现的接口
handler : 动态代理类的实现类
动态代理的好处:
减少编程的工作量,加入要实现多个代理的逻辑,只要写多个代理处理器就可以了,无需每种方式都写一个代理类。
系统扩展性和维护性增强。
适配器模式 Adapter Pattern
什么是适配器模式?
将一个类的接口转换为客户希望的另外一个接口,Adapter 模式能让原本接口不匹配,不能一起工作的类可以一起工作。
组合方式(对象适配器): ① 添加一个元接口,增加功能方法 添加实现类,并重写功能方法
② 添加一个目标接口,增加功能方法 添加实现类,并重写其功能方法
③ 添加适配器类 实现元接口,添加带有目标接口对象的构造方法,重写元方法,使用目标接口对象调用目标方法
继承方式(类适配器):① 添加一个元接口,增加功能方法 添加实现类,并重写功能方法
② 添加一个目标接口,增加功能方法 添加实现类,并重写其功能方法
③ 添加适配器类 继承目标接口的实现类 并实现元接口,重写元接口中的方法,采用super.目标方法()调用;
两种方式的区别: 组合方式:采用组合方式的适配器结构称为 对象适配器。
把"被适配器"组一个对象组合到适配器中,以修改目标接口包装被适配器。
继承方式:采用继承方式的适配器称为 类适配器。
通过多重继承不兼容的接口,实现对目标接口的匹配,单一为某个类的实现而适配。
特点: 透明、重用、低耦合
适用场景:在想适用一个已经存在类的接口时,但如何它的接口或者它的方法与你的要求不同时,就可以采用适配器模式。
策略模式 Strategy Pattern
什么是策略模式?
它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到调用算法的用户。
策略算法是相同行为的不同实现。
实现步骤:
① 添加抽象的策略父类 Strategy
② 添加实现抽象类的子类
③ 定义 Factory 工厂生产策略对象
④ 定义 Content 调用功能
优点:
策略模式提供了管理相关的算法家族的办法
策略模式提供了可以替换继承关系的办法
使用策略模式可以避免使用多重条件转移的语句
应用场景:
多个类只区别在表现行为不同,可以使用 Strategy 模式,在运行时动态选择具体要执行的行为。
模板模式 Template Method Pattern
什么是模板模式?
定义一个操作中的算法的骨架,而这些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。
钩子方法:
在模板方法中,添加一个可以被子类重写,返回结果为 Boolean 类型的方法,用来判断是否需要执行特定的一些操作。
优点:
模板方法模式在一个类中形式化地定义算法,而由它的子类实现细节的处理
模板方法是一种代码复用的基本技术
模板方法模式导致一种反向的控制结构,“好莱坞法则”,即通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”
缺点:
导致类的个数增加,但更符合“单一职责原则”
适用场景:
一次性实现一个算法的不变部分,并将可变的行为留给子类来实现,需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。
暂列几种常用的,如需其他详细的请查看:https://download.csdn.net/download/darryl_tang/10644355