java - 设计模式
设计模式是一种设计思想,解决方案,经验总结。
reference:
http://c.biancheng.net/view/1354.html
https://www.bilibili.com/video/av57936239?p=45
6大原则:
单一职责:类和方法有唯一的职责。 (提高可读性,降低耦合)
接口隔离原则:接口尽量细化,每个子类只继承需要的接口,而不能把很多功能集中在一个大接口中让子类继承。(使用多个专门的接口比使用单一的总接口要好,降低重复性)
依赖倒转原则:类的最底层最好是抽象类和接口(因为细节经常变动,所以抽象的更比具体的更稳定,更适合作为底层模块)。
里式替换原则:程序中,即使用一个类的子类替换它,也不会影响程序的运行。(说明子类没有修改父类的方法,只是在其基础上增加了新的方法和属性)
开闭原则ocp :抽象构建矿建,实体扩展细节。开放扩展(程序可以增加功能,通过实体化增加细节(创建新的子类)),关闭修改(增加的功能尽量不修改之前的功能)。(防止修改代码影响已有代码的使用,或者影响其他开发者的使用)
迪米特法则 :对象对其他对象保持最小了解。类之间保持低耦合。(比如属性设为private,get,set方法设为public就是这个原则的提现)
合成复用原则(有的版本没有这个原则): 尽量合成,而不是继承。(A想用B的方法。在A中创建B对象然后使用,比直接继承B要好。)(A继承B,结果B中有和A重名的方法,会被A的覆盖,然后影响使用。)
java的设计模式大体上分为三大类:
创建型模式(5种): 用于解决结局对象创建
单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式。
结构型模式(7种):把类和对象结合在一起,构成复杂结构
适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
行为型模式(11种): 解决类或对象之间的交互,优化类或者对象之间的关系
观察者模式、策略模式、模板方法模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
1.1 创建型模式 - 单例模式(Singleton)
如果是为了应付面试- -这个问的最多。
如果一个类中只有方法会被大量使用,没必要每次都创建一个新实例,只创建一个实例,每次都调用这个实例的方法就可以
让这个类永远只能创建一个对象。(有点类似于static)
优点:
保证这个类只有一个,不需要重复创建。可以用来处理重量级(很多方法和属性的)类
package xiushifu.singleton; //如果一个类中只有方法会被大量使用,没必要每次都创建一个新实例,只创建一个实例,每次都调用这个实例的方法就可以 //让一个类只创建一个对象。 //在内部创建一个实例,构造器全部设置为private,所有方法均在该实例上改动,在创建上要注意类的实例化只能执行一次,可以采用许多种方法来实现,如Synchronized关键字,或者利用内部类等机制来实现。 //1.让构造方法变成私有 //2.通过static控制创建 public class SingleTon { private SingleTon(){}//将构造方法变为私有,不能通过外部随意创建 //饿汉式 private static SingleTon singleton = new SingleTon(); //static 表示所有实例的这个变量都被存在一个空间内,每次修改都会覆盖掉之前的值,保证了实例只有一个。 public static SingleTon newInstance(){ //可以通过class直接调用。 return singleton; //因为属性也是私有的,所以需要一个公有方法来获取。 } //懒汉式 使用这种则不能直接在class里直接用this.singleton了,否则会空指针。 // private static SingleTon singleton; //static 表示所有实例的这个变量都被存在一个空间内,每次修改都会覆盖掉之前的值,保证了实例只有一个,不直接创建实例,需要时再创建。 // // public static SingleTon newInstance(){ //可以通过class直接调用。 // if(singleton == null){ //判断之前是否被调用过,如果是第一次则创建实例 // singleton = new SingleTon(); // } // return singleton; //因为属性也是私有的,所以需要一个公有方法来获取。 // } public static void main(String[] args) { // SingleTon.singleton就是一个初始化完毕的实例,它是属于类的,这样保证了只有一个。 SingleTon s1 = SingleTon.singleton;//因为属性是private,所以这种写法只能在本类中使用 SingleTon s2 = SingleTon.singleton; System.out.println(s1 == s2);//判断s1和s2的内存地址hashcode值是否一致。 返回一个16进制数字 System.out.println(s1.equals(s2));//底层代码其实和s1==s2一样 SingleTon s3 = SingleTon.newInstance();//可以在外部类中使用,和上面效果一样 SingleTon s4 = SingleTon.newInstance(); System.out.println(s3 == s4); System.out.println(s1 == s3); } }
共有方法返回单例对象:
饿汉式:立即加载 启动项目就已经加载了,所以可能会浪费空间,不会产生空指针。 上面的是饿汉式
懒汉式:延迟加载 用到了才会加载,可能会异常,用到了才会加载(在public方法中new)不会浪费空间。
生命周期托管:其他对象处理
1.2 创建型模式 - 工厂模式
工厂,商品,用户3个类
商品的创建交给工厂来实行,而不是用户创建,这样可以保证创建和使用分离。
1.用户不需要知道商品的创建过程
2.添加新商品时创建新的工厂类就好,不需要修改现有类。
1.3 创建型模式 - 抽象工厂模式
其实就是工厂模式改进版,用抽象类或者接口统一设计一类工厂和商品。
抽象工厂,工厂,抽象商品,商品,用户5个类
商品的创建交给工厂来实行,而不是用户创建,这样可以保证创建和使用分离。
不同商品共同父类,交给工厂生产,不同工厂共同父类,生产不同产品。
用户准备使用时直接用子工厂创建对应商品。
优点:
1.用户不需要知道商品的创建过程
2.添加新商品时创建新的商品子类就好,不需要修改现有类。
1.4 创建型模式 - 建造者模式
主要用于一个由多部分组成的对象的创建。
产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个滅部件。
抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
想要创建一个产品角色时,指挥者可以调用具体建造者中的方法分别创建产品角色中的各个部分(给所有属性赋值),最后返回对象。
优点:
适用于被创建对象有很多复杂的部分组成,每个部分创建方式可能有改动,但是整体结构稳定的情况。这样修改时只需要修改具体建造者的对应方法就可以。不需要修改指挥者,产品和抽象建造者。
1.5 创建型模式 - 原型模式
说白了就是在已有对象基础上复制一个新的。
因为java现在Object类提供了clone()方法,所以复制非常简单。复制后只需修改复制体不同的部分即可。
抽象原型类:规定了具体原型对象必须实现的接口。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。
优点:
快速创建多个相似或者相同的对象。
适用于大量创建属性很多,但是区别很小的对象。
2.1 设计模式 - 适配器模式(Adapter)
在两个类之间添加适配器接口,起到过渡作用。主要处理第三方提供接口的和本地接口不一致,有个例不符合接口规范等情况。
目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
1. 缺省适配器:
解决某个类型中出现了个例
在类和实例之间添加适配器,使实例可以不用拥有所有类的属性。
和尚:念经,打坐,习武 接口interface
适配器 abstract class:具体化不是很重要的方法不需要有具体内容{},让子类实现根据实际情况选择实现。implements interface
鲁智深:只习武 class extends abstract class
2. 双向适配器
解决两钟接口之间的转换
A: 念经
B:打坐
双向适配器:念经,打坐 (同时继承A接口和B接口,使用的时候直接用这个适配器创建对象,想用哪个用哪个)
2.2 设计模式 - 代理模式
用户不直接访问指定对象,而是添加一个代理类来访问,这样可以在中间进行特殊处理(我猜的: spring中的AOP实现,就是添加了一层代理类,把写的类中的方法加入代理类,这样想添加前置或者后置业务的时候,直接在代理类中添加。)
抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
3. 行为模式- 策略模式(Strategy)
方法抽象,根据对象不同进行具体实现,用来解决流程固定,结果根据情况不同。
多态