本文所有案例代码
码云:https://gitee.com/helloworld6379/designPattern
Github:Github地址
设计模式概述
1 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是某类问题的通
用解决方案,设计模式(Design pattern)代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的
一段时间的试验和错误总结出来的。
2 设计模式的本质提高 软件的维护性,通用性和扩展性,并降低软件的复杂度。
3 设计模式并不局限于某种语言,java,php,c++ 都有设计模式.
设计模式类型
设计模式分为三种类型,共 23 种
1 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式。
2 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
3 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter 模式)、状态模式、策略模式、职责链模式(责任链模式)。
适配器模式
生活中的例子:
欧洲的大部分国家的插座都是圆形的,而我国的都是矩形的,
很多国内去国外旅游留学或者做生意的,带上国内的手机笔记本就不能充电了,
需要适配器。
在国内上过大学的都知道,国内大学宿舍内用电器都是限压的,
很多学生想用热得快或者火锅,就需要适配器来增加电压。
意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类系中。
如何解决:继承或依赖(推荐)。
关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
应用实例: 1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。 2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。 3、在 LINUX 上运行 WINDOWS 程序。 4、JAVA 中的 jdbc。
优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。
缺点: 1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。
主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。
类适配器模式
UML图
/**
* @Description 天朝插排接口
* @Author: LiuXing
* @Date: 2020/5/26 23:25
*/
public interface ChinaSocketInterface {
//方形两头充电
void chargeByTwoRectangle();
}
/**
* @Description 天朝插排实现接口
* @Author: LiuXing
* @Date: 2020/5/26 23:25
*/
public class ChinaSocket implements ChinaSocketInterface {
@Override
public void chargeByTwoRectangle() {
System.out.println("天朝插排使用矩形两头的插孔供电");
}
}
/**
* @Description 意大利插排接口
* @Author: LiuXing
* @Date: 2020/5/26 23:26
*/
public interface ItalySocketInterface {
//圆形两头充电
void chargeByTwoRound();
}
/**
* @Description 意大利插排实现接口
* @Author: LiuXing
* @Date: 2020/5/26 23:26
*/
public class ItalySocket implements ItalySocketInterface {
@Override
public void chargeByTwoRound() {
System.out.println("意大利插排使用圆形两头的插孔供电");
}
}
/**
* @Description 适配器,被天朝的家电使用
* @Author: LiuXing
* @Date: 2020/5/26 23:26
*/
public class SocketAdapter extends ItalySocket implements ChinaSocketInterface{
@Override
public void chargeByTwoRectangle() {
this.chargeByTwoRound();
}
}
/**
* @Description 天朝家电
* @Author: LiuXing
* @Date: 2020/5/26 23:25
*/
public class ChineseJD {
public void charge(ChinaSocketInterface chinaSocketInterface){
chinaSocketInterface.chargeByTwoRectangle();
}
}
/**
* @Description 类适配器模式测试
* @Author: LiuXing
* @Date: 2020/5/26 23:26
*/
public class SocketInterfaceTest {
public static void main(String[] args) {
ChineseJD chineseJD = new ChineseJD();
chineseJD.charge(new SocketAdapter());
}
}
对象适配器模式
1、基本思路和类的适配器模式相同,只是将 SocketAdapter 类作修改,不是继承 ItalySocket 类,而是持有 ItalySocket 类的实例,以解决 兼容性的问题。 即:持有 ItalySocket 类,实现 ChinaSocketInterface类接口,
2、 根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来替代继承关系。
3 、对象适配器模式是适配器模式常用的一种。
UML图
/**
* @Description 天朝插排接口
* @Author: LiuXing
* @Date: 2020/5/26 23:25
*/
public interface ChinaSocketInterface {
//方形两头充电
void chargeByTwoRectangle();
}
/**
* @Description 天朝插排实现接口
* @Author: LiuXing
* @Date: 2020/5/26 23:25
*/
public class ChinaSocket implements ChinaSocketInterface {
@Override
public void chargeByTwoRectangle() {
System.out.println("天朝插排使用矩形两头的插孔供电");
}
}
/**
* @Description 意大利插排接口
* @Author: LiuXing
* @Date: 2020/5/26 23:26
*/
public interface ItalySocketInterface {
//圆形两头充电
void chargeByTwoRound();
}
/**
* @Description 意大利插排实现接口
* @Author: LiuXing
* @Date: 2020/5/26 23:26
*/
public class ItalySocket implements ItalySocketInterface {
@Override
public void chargeByTwoRound() {
System.out.println("意大利插排使用圆形两头的插孔供电");
}
}
/**
* @Description 适配器
* @Author: LiuXing
* @Date: 2020/5/26 23:37
*/
public class SocketAdapter implements ChinaSocketInterface {
//不再继承而是持有引用
private ItalySocket socket;
public SocketAdapter (ItalySocket socket) {
this.socket = socket;
}
@Override
public void chargeByTwoRectangle() {
this.socket.chargeByTwoRound();
}
}
/**
* @Description 天朝家电
* @Author: LiuXing
* @Date: 2020/5/26 23:25
*/
public class ChineseJD {
public void charge(ChinaSocketInterface chinaSocketInterface){
chinaSocketInterface.chargeByTwoRectangle();
}
}
/**
* @Description 对象适配器模式
* @Author: LiuXing
* @Date: 2020/5/26 23:32
*/
public class SocketInterfaceTest {
public static void main(String[] args) {
ChineseJD chineseJD = new ChineseJD();
chineseJD.charge(new SocketAdapter(new ItalySocket()));
}
}
接口适配器模式
核心思路:当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供 一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求
适用于一个接口不想使用其所有的方法的情况。
UML图:
public interface USB {
/**充电*/
public void charge();
/**传输文件*/
public void transferFiles();
/**键盘*/
public void keyboard();
/**鼠标*/
public void mouse();
}
public abstract class USBAdapter implements USB {
@Override
public void charge() {
}
@Override
public void transferFiles() {
}
@Override
public void keyboard() {
}
@Override
public void mouse() {
}
}
public class Computer {
private USB usb;
public void setUSB(USB usb){
this.usb = usb;
}
public void charge() {
usb.charge();
}
public void transferFiles() {
usb.transferFiles();
}
public void keyboard() {
usb.keyboard();
}
public void mouse() {
usb.mouse();
}
}
public class DefaultAdapterTest {
public static void main(String[] args) {
// 1、原来要实现所有操作类的操作
Computer computer = new Computer();
computer.setUSB(new USB() {
@Override
public void charge() {
System.out.println("充电");
}
@Override
public void transferFiles() {
}
@Override
public void keyboard() {
}
@Override
public void mouse() {
}
});
computer.charge();
// 2、使用缺省适配器只需要实现需要用到的接口方法
Computer computer2 = new Computer();
computer2.setUSB(new USBAdapter() {
@Override
public void charge() {
System.out.println("充电");
}
});
computer2.charge();
}
}
适配器模式在 SpringMVC 中的应用
SpringMVC中我们最熟悉的DispatcherServlet和HandlerAdapter就使用了适配器模式
Spring定义了一个适配器接口HandlerAdapter,使得每一种controller都有一个对应的适配器实现类。
适配器实现类代替controller执行controller中的方法。
想要扩展Controller,只需要添加一个适配器就能完成SpringMVC的扩展。