Java设计模式:23种设计模式全⾯解析(超级详细)以及在源码中的应⽤
从⽹络上的设计模式, 很全⾯,只要把UML类图看懂了, 照着类图将代码实现是很容易的事情.
步骤: 先看懂类图, 然后将代码实现, 之后再看⽂字
7⼤设计原则:
1: 单⼀职责原则: 类应该只有⼀个职责,或者功能
2: 接⼝隔离原则: ⼀个类不应该依赖与他不相关,不需要的接⼝, ⼀个类对另⼀个类的依赖应该建⽴在最⼩的接⼝上
3: 依赖倒置原则: 依赖抽象不依赖具体,思想是:⾯向接⼝编程
4: ⾥⽒替换原则: java中的继承有弊端, 少⽤继承, 多使⽤聚合,组合,依赖, 因为⼦类继承后,很容易不⼩⼼将⽗类中的⽅法重写, ⽽⼦类不知道,调⽗类⽅法时候,容易混淆, 换句话就是:所有使⽤⽗类⽅
法的地⽅,也能透明的使⽤其⼦类的对象, ⼦类尽量不要重写⽗类的⽅法, 可以将⽗类和⼦类都继承⼀个更通俗的⽗类,
5: 开闭原则(ocp原则): 对扩展开放(提供⽅), 对修改关闭(使⽤⽅)
6: 迪⽶特原则: 最少知道原则, ⼀个类对⾃⼰依赖的类知道越少越好,被依赖的类尽量将逻辑都封装到类中,只提供外⼀个⼊⼝就好, ⼜叫: 只和直接朋友通信,(直接朋友:成员变量,⽅法⼊参, ⽅法返回
值中的类都是直接朋友, 局部变量中的类不是直接朋友, 也就是说陌⽣的类,不要以局部变量的⽅式出现在类中)
7: 合成复⽤原则: 尽量使⽤聚合,组合的⽅式, 少⽤继承, 这样做⽬的是松耦合
⼀: 1.1:简单⼯⼚模式(⼜叫静态⼯⼚模式): 是将各种对象的创建都交给⼀个⼯⼚类, client要使⽤各种对象时候,只需要在client中聚合这个⼯⼚类即可,
⽐如这个图中,胡椒披萨,榴莲披萨,原味披萨, 都有⼀个共同的基类Pizza, ⼯⼚类SimpleFactory 根据不同类型返回对应的披萨对象,, OrderPizza这个就是client类, 在OrderPizza类中聚合⼯⼚类即可, 就可以根据不同类型创造不同⼝味的披萨了
1.2: ⼯⼚⽅法模式: 假如有北京胡椒披萨,北京榴莲披萨,北京原味披萨, 伦敦胡椒披萨,伦敦榴莲披萨,伦敦原味披萨. 此时使⽤简单⼯⼚模式是不合适的, 等于在这个⼯⼚类中,要分别创建这6个披萨对象, 修改多,维护性,扩展性差 .解决⽅法: 简单⼯⼚模式是创建了⼀个⼯⼚类, ⼯⼚⽅法模式,是创建⼀个抽象⼯⼚类,他的实现是北京⼯⼚类, 伦敦⼯⼚类, 在实现类中完成对象的创建,
这样等于是,将对象的创建交给⼦类取实现.uml类图如下:
1.3: 抽象⼯⼚模式: ⼯⼚⽅法模式是创建了⼀个抽象⼯⼚类,让⼦类取实现,完成对象创建, 很相似抽象⼯⼚模式是定义⼀个接⼝, 对象的创建在⼦类中完成.client中聚合该接⼝类,uml类图如下
⼯⼚模式再JDK源码中的应⽤
Calendar date = Instance();
public static Calendar getInstance(){
return Default(), Default(Locale.Category.FORMAT));
}
再点进去
private static Calendar createCalendar(TimeZone zone,Locale aLocale){
CalendarProvider provider =
.getCalendarProvider();
if (provider != null) {
try {
Instance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
//这⾥根据时区不同,来创建不同的对象
String caltype = UnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (Language() == "th" && Country() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (Variant() == "JP" && Language() == "ja"
&& Country() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
⼆: 原型模式: 原型模式就是将⼀个对象复制出另⼀个对象来,除了内存地址不同,其余都相同, 使⽤Object类中的clone⽅法, 如果⼀个对象中的属性都是基本数据类型, 使⽤clone⽅法就可以实现对象的复制, 如果该对象中的属性,有引⽤数据类型(数组,另⼀个对象,list,)此时使⽤clone⽅法,不能实现对
象的完全复制, 因为引⽤数据类型,使⽤clone⽅法,在内存中只是指针的引⽤,并没有重新复制出相同的对象来,,,, 建议使⽤流序列化的⽅式实现深拷贝
原型模式在spring中的应⽤, spring中的bean的创建, xml⽂件中配置这⾥的 scope="prototype"就是指对象多例模式, 其实就是原型模式,复制⼀模⼀样的对象
三: 建造者模式: 将复杂对象的建造过程抽象出来, 从⽽他的实现类可以构造出不同属性的对象, ⽤户只需要指定复杂对象的类型和内容,就可以建造他们,不需要知道具体的建造过程. ⽐如房⼦建造过程: 打地基,砌墙,封顶, 他的实现类:普通房⼦实现类, 创建的对象:普通房⼦,地基150cm,墙厚15cm,顶是茅草顶, 另⼀个实现类:豪宅,创建的对象: 地基300cm,墙厚50cm,顶是⾦砖顶.
有四个⾓⾊:
1:产品(product)
2:抽象建造者(builder), 创建⼀个product对象的各个部件指定的接⼝或抽象类
3:具体建造者(concreateBuilder) 实现接⼝,构建和装配各个配件
4:指挥者(director) , 构建⼀个使⽤ builder接⼝的对象,它主要创建⼀个复杂对象, 隔离了客户与产品的制造过程, 负责控制产品的制造流程
uml类图如下:
该图中,产品product 是组合到 builder抽象类中的,这样builder的实现类,都可以拿到product,从⽽对其属性,⽅法进⾏各⾃的实现, builder 和 director(指挥者)的关系是聚合, 同
时,director类中,会有⼀个总的build⽅法,作为对外提供的接⼝, client端使⽤的时候,只需要使⽤ director类的 builder ⽅法,就可建造不同类型的产品了.
建造者模式在 JDK 中的应⽤, ⽐如:StringBuilder
建造者模式和抽象⼯⼚模式对⽐, 建造者模式是隔离了客户和产品建造过程, ⽽抽象⼯⼚模式,没有隔
实例化类和实例化对象离,在client中调⽤时候,需要具体实现者⼀步⼀步建造产品, 这样如果再有⼀个房⼦的产品,地基500cm,墙600cm,没有顶, 相对于建造者模式来说,修改很容易, ⽽抽象⼯⼚模式来说,相当于⼜把建造流程写了⼀遍,不利于维护和扩
展 uml对⽐如下
四: 适配器模式: ⽬的是兼容, 将某个类的接⼝转换成客户期望的另⼀个接⼝表⽰,让原本因为接⼝不匹配⽽不能⼀起⼯作的⼆个类可以协同⼯作, 从客户的⾓度看不到适配过程,感觉只是和⽬标类接⼝交互,uml类图如下, 类之间的关系 Voltage5V这个是适配器接⼝,Voltage220V是被适配类, VoltageAdapter是适配器实现类, 实现适配器接⼝,并继承被适配类,
类适配器UML类图
之前说过继承不好,可以⽤聚合来代替, 对象适配器UML类图如下:
类适配器模式, 对象适配器模式, 都是适配器接⼝, ⽽接⼝适配器模式, 是将适配器接⼝做成抽象类, 被适配类(220V)做成接⼝, 抽象类实现该接⼝, 这样client使⽤的时候,直接使⽤抽象类,并重写⽅法就可以了,很简单很灵活, 接⼝适配器模式UML类图如下:
适配器模式在SpringMVC 中的应⽤: 相信这个图我们都很熟悉了,
client发送请求到 DispatchServlet, ,,,,请求执⾏Hander, 这个请求就是发给了处理器适配器,HandlerAdapter, 因为处理器的类型很多,spring定义这个接⼝,使得每⼀种Controller都有对应的适配器实现类, 适配器代替controller执⾏相应的⽅法, controller和适配器的类图如下:
五:桥接模式: 就是将抽象化(Abstraction) 和实现化(inplermentation) 分开,使⼆者可以独⽴变化, UMl类图如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论