设计模式(学习笔记)
创建型模式
创建者模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为:
- 单例模式
- 工厂方法模式
- 抽象工程模式
- 原型模式
- 建造者模式
深入理解Java并发之synchronized实现原理-CSDN博客
通过反射破坏单例模式:
原型模式
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
原型模式包含如下角色:
- 抽象原型类:规定了具体原型对象必须实现的clone()方法。
- 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象。
- 访问类:使用具体原型类中的clone()方法来复制新的对象。
原型模式的克隆分为浅克隆和深克隆。
浅克隆:创建一个新的对象,新对象的属性和原有对象完全相同,对于非基本类型属性,仍指向原有属性的对象的内存地址。
深克隆:创建一个新的对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
Java中的Object类中提供了clone()方法来实现浅克隆。Cloneable接口是上面的类图中的抽象原型类,而实现Cloneable接口的子实现类就是具体的原型类。
克隆之间的关系是false的原因:判断的属性不是类变量!另外,false意味着改变克隆的值,不会改变被克隆的值,也就是说,克隆的内存是新开辟的!
克隆之间的关系是true的原因:克隆的是实现了Cloneable的类Citation,判断的是这个类中的类变量属性Person!另外true意味着,克隆对象与被克隆的对象的内存地址是相同的。
深克隆:
实现深克隆的关键是在具体的子类中实现Cloneable接口,并重写具体的clone方法。
说明:
stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性改为"李四",两个Citation对象中显示的都是李四,这就是浅克隆的效果,对具体原型类中的引用类型的属性进行引用的复制。这种情况需要使用深克隆,进而进行深克隆需要使用对象流。
深克隆
/asa///**********************************
结构型模式
结构性模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者采用组合或聚合来组合对象。
由于组合关系或聚合关系比继承关系耦合度低,满足“合成符用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
结构型模式分为以下7种:
- 代理模式
- 适配器模式
- 装饰者模式
- 桥接模式
- 外观模式
- 组合模式
- 享元模式
从上面代码中可以看出测试类直接访问的是ProxyPoint类对象,也就是说ProxyPoint作为访问对象和目标对象的中介。同时也对sell方法进行了增强(代理点收取一些服务费)。
JDK动态代理
接下来我们使用动态代理实现上面案例,先说说JDK提供的动态代理。Java中提供了一个动态代理类Proxy,Proxy并不是我们上述所说的代理对象类,而是提供了一个创建代理对象的静态方法(newProxyInstance方法)来获取代理对象。
回调函数是啥?
三种代理模式的对比
jdk代理和CGLIB代理:
使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架......
动态代理与静态代理:
动态代理和静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题。
代理模式的优点:
- 代理对象在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
- 代理对象可以扩展目标对象的功能
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。
代理模式的缺点:
增加了系统的复杂度
使用场景
远程(Remote)代理
本地服务通过网络请求远程服务。为了实现本地到远程的通信,我们需要实现网络通信,处理其中可能得异常。为良好的代码设计和可维护性,我们将网络通信部分隐藏起来,只暴露给本地服务一个接口,通过该接口即可访问远程服务提供的功能,而不必过多关心通信部分的细节。
防火墙(Firewall)代理
当你将浏览器配置成使用代理功能时,防火墙就将你的浏览器的请求转给互联网;当互联网返回响应时,代理服务器再把它转给你的浏览器。
保护(Protect or Access)代理
控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。
RPC框架
好处:
- 装饰者模式可以带来比继承更加灵活性的拓展功能,使用更加方便,可以通过组合不同的装饰者来获取具有不同行为状态的多样化的结果。装饰者模式比继承更具有良好的扩展性,完美的遵循开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任。
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
使用场景
- 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
- 不能采用继承的情况主要有两类:
- 第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长
- 第二类是因为类定义不能继承(如final 类)
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时。
代理模式和装饰者模式的区别
静态代理和装饰者模式的区别:
相同点:
- 都要实现与目标类相同的业务接口
- 在两个类中都要声明目标对象
- 都可以在不修改目标类的前提下增强目标方法
不同点:
- 目的不同:装饰者是为了增强目标对象,静态代理是为了保护和隐藏目标对象
- 获取目标对象构建的地方不同:装饰者是由外界传递进来的,可以通过构造方法传递,静态代理是在代理类内部创建,以此来隐藏目标对象。
定义:
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
结构
桥接(Bridge)模式包含一下主要角色:
- 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化角色:给出实现化角色接口的具体实现。
外观模式
有些人可能炒过股票,但其实大部分人都不太懂,这种没有足够了解证券知识的情况下做股票是很容易亏钱的,刚开始炒股肯定都会想,如果有个懂行的帮帮手就好,其实基金就是个好帮手,支付宝里就有许多的基金,它将投资者的资金集中起来,交由专业的经理人进行管理,投资于股票、债券、外汇等领域,而基金投资的收益归持有者所有,管理机构收取一定比例的托管管理费用。
定义:
又名门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
public class Light {
public void on() {
System.out.println("打开电灯......");
}
public void off() {
System.out.println("关闭电灯......");
}
}
享元模式
定义:
运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象的数量、避免大量相似对象的开销,从而提高系统资源的利用率。