设计模式

1、简述

GoF23种设计模式。

2、基本要素

模式名称、问题、解决方案、效果

3、23种设计模式

image.png
创建型模式:让创建和使用分离
结构型模式:让类和对象组成更大的结构
行为型模式:让类和对象相互协作完成单个对象无法完成的任务

4、OOP七大原则

开闭原则
里氏替代原则:子类可以扩展方法但父类方法尽量不要改动
依赖倒置原则:面向接口编程
单一职责原则:粒度,一个方法尽可能处理一件事情,说的是具体实现
接口隔离原则:和单一职责原则差不多,说的是接口
迪米特法则:和朋友直接交谈、不跟陌生人交谈
合成复用原则:尽量使用has-a,避免使用is-a

5、工厂设计模式

作用:
分类:
简单工厂模式:也叫静态工厂模式,以工厂类代替new。缺点:违背开闭原则
工厂方法模式:
抽象工厂模式:

传统方式

image.png

  1. package model.factory.tradition;
  2. public interface Car {
  3. void name();
  4. }
  1. package model.factory.tradition;
  2. public class WuLing implements Car {
  3. @Override
  4. public void name() {
  5. System.out.println("五菱宏光");
  6. }
  7. }
  1. package model.factory.tradition;
  2. public class Tesla implements Car {
  3. @Override
  4. public void name() {
  5. System.out.println("Tesla");
  6. }
  7. }
  1. package model.factory.tradition;
  2. //传统情况
  3. public class Consumer {
  4. public static void main(String[] args) {
  5. Car car1 = new WuLing();//五菱宏光
  6. Car car2 = new Tesla();//Tesla
  7. car1.name();
  8. car2.name();
  9. }
  10. }

image.png

缺点

调用者与实现者高度耦合,需要new

简单工厂模式

image.png

  1. package model.factory.simple;
  2. public interface Car {
  3. void name();
  4. }
  1. package model.factory.simple;
  2. public class WuLing implements Car {
  3. @Override
  4. public void name() {
  5. System.out.println("五菱宏光");
  6. }
  7. }
  1. package model.factory.simple;
  2. public class Tesla implements Car {
  3. @Override
  4. public void name() {
  5. System.out.println("Tesla");
  6. }
  7. }
  1. package model.factory.simple;
  2. public class CarFactory {
  3. public static Car getCar(String car){
  4. if ("五菱宏光".equals(car)){
  5. return new WuLing();
  6. }else if ("Tesla".equals(car)){
  7. return new Tesla();
  8. }else {
  9. return null;
  10. }
  11. }
  12. }
  1. package model.factory.simple;
  2. public class Consumer {
  3. public static void main(String[] args) {
  4. Car car1 = CarFactory.getCar("五菱宏光");
  5. Car car2 = CarFactory.getCar("Tesla");
  6. car1.name();//五菱宏光
  7. car2.name();//Tesla
  8. }
  9. }

image.png

优点

代码简单,实现容易

缺点

不满足开闭原则

工厂方法模式

image.png

  1. package model.factory.method;
  2. public interface Car {
  3. void name();
  4. }
  1. package model.factory.method;
  2. public class WuLing implements Car {
  3. @Override
  4. public void name() {
  5. System.out.println("五菱宏光");
  6. }
  7. }
  1. package model.factory.method;
  2. public class Tesla implements Car {
  3. @Override
  4. public void name() {
  5. System.out.println("Tesla");
  6. }
  7. }
  1. package model.factory.method;
  2. public interface CarFactory {
  3. public Car getCar();
  4. }
  1. package model.factory.method;
  2. public class WuLingFactory implements CarFactory {
  3. @Override
  4. public Car getCar() {
  5. return new WuLing();
  6. }
  7. }
  1. package model.factory.method;
  2. public class TeslaFactory implements CarFactory {
  3. @Override
  4. public Car getCar() {
  5. return new Tesla();
  6. }
  7. }
  1. package model.factory.method;
  2. public class Consumer {
  3. public static void main(String[] args) {
  4. Car car1 = new WuLingFactory().getCar();
  5. Car car2 = new TeslaFactory().getCar();
  6. car1.name();//五菱宏光
  7. car2.name();//Tesla
  8. }
  9. }

优点

扩展性好,即使后面来了大众、宝马等车,也满足代码的开闭原则

缺点

写的类有点多
image.png

抽象工厂模式

image.png

  1. package model.factory.abstract0;
  2. public interface PhoneProduct {
  3. public void callUp();
  4. public void sendMsg();
  5. }
  1. package model.factory.abstract0;
  2. public class XiaomiProduct implements PhoneProduct {
  3. @Override
  4. public void callUp() {
  5. System.out.println("小米手机打电话");
  6. }
  7. @Override
  8. public void sendMsg() {
  9. System.out.println("小米手机发消息");
  10. }
  11. }
  1. package model.factory.abstract0;
  2. public class HuaweiProduct implements PhoneProduct {
  3. @Override
  4. public void callUp() {
  5. System.out.println("华为手机打电话");
  6. }
  7. @Override
  8. public void sendMsg() {
  9. System.out.println("华为手机发消息");
  10. }
  11. }
  1. package model.factory.abstract0;
  2. public interface PhoneRounter {
  3. void openWifi();
  4. void closeWifi();
  5. }
  1. package model.factory.abstract0;
  2. public class XiaomiRounter implements PhoneRounter {
  3. @Override
  4. public void openWifi() {
  5. System.out.println("打开小米路由器");
  6. }
  7. @Override
  8. public void closeWifi() {
  9. System.out.println("关闭小米路由器");
  10. }
  11. }
  1. package model.factory.abstract0;
  2. public class HuaweiRounter implements PhoneRounter {
  3. @Override
  4. public void openWifi() {
  5. System.out.println("打开华为路由器");
  6. }
  7. @Override
  8. public void closeWifi() {
  9. System.out.println("关闭华为路由器");
  10. }
  11. }
  1. package model.factory.abstract0;
  2. public interface PhoneFactory {
  3. PhoneProduct phoneProduct();
  4. PhoneRounter phoneRouter();
  5. }
  1. package model.factory.abstract0;
  2. public class XiaomiFactory implements PhoneFactory {
  3. @Override
  4. public PhoneProduct phoneProduct() {
  5. return new XiaomiProduct();
  6. }
  7. @Override
  8. public PhoneRounter phoneRouter() {
  9. return new XiaomiRounter();
  10. }
  11. }
  1. package model.factory.abstract0;
  2. public class HuaweiFactory implements PhoneFactory {
  3. @Override
  4. public PhoneProduct phoneProduct() {
  5. return new HuaweiProduct();
  6. }
  7. @Override
  8. public PhoneRounter phoneRouter() {
  9. return new HuaweiRounter();
  10. }
  11. }
  1. package model.factory.abstract0;
  2. public class Consumer {
  3. public static void main(String[] args) {
  4. PhoneProduct xiaomiPhone = new XiaomiFactory().phoneProduct();
  5. xiaomiPhone.callUp();//小米手机打电话
  6. xiaomiPhone.sendMsg();//小米手机发消息
  7. PhoneRounter huaweiRouter = new HuaweiFactory().phoneRouter();
  8. huaweiRouter.openWifi();//打开华为路由器
  9. huaweiRouter.closeWifi();//关闭华为路由器
  10. }
  11. }

image.png

优点

具体产品在应用层的代码隔离,无需关心创建的细节;
将一个系列的产品统一到一起创建

缺点

扩展性差;
增加了系统的抽象性和理解难度

6、建造者模式

image.png

  1. package model.factory.builder;
  2. //抽象建造者
  3. //建造一个产品需要经历几个步骤
  4. public abstract class Builder {
  5. abstract void builderA();//地基
  6. abstract void builderB();//钢筋工程
  7. abstract void builderC();//铺电缆
  8. abstract void builderD();//粉刷
  9. //完工:得到产品
  10. abstract Product getProduct();
  11. }
  1. package model.factory.builder;
  2. public class Product {
  3. private String BuildA;
  4. private String BuildB;
  5. private String BuildC;
  6. private String BuildD;
  7. @Override
  8. public String toString() {
  9. return "Produt{" +
  10. "BuildA='" + BuildA + '\'' +
  11. ", BuildB='" + BuildB + '\'' +
  12. ", BuildC='" + BuildC + '\'' +
  13. ", BuildD='" + BuildD + '\'' +
  14. '}';
  15. }
  16. public String getBuildA() {
  17. return BuildA;
  18. }
  19. public void setBuildA(String buildA) {
  20. BuildA = buildA;
  21. }
  22. public String getBuildB() {
  23. return BuildB;
  24. }
  25. public void setBuildB(String buildB) {
  26. BuildB = buildB;
  27. }
  28. public String getBuildC() {
  29. return BuildC;
  30. }
  31. public void setBuildC(String buildC) {
  32. BuildC = buildC;
  33. }
  34. public String getBuildD() {
  35. return BuildD;
  36. }
  37. public void setBuildD(String buildD) {
  38. BuildD = buildD;
  39. }
  40. }
  1. package model.factory.builder;
  2. //工人就完成这些步骤和返回结果
  3. public class Worker extends Builder {
  4. private Product product;
  5. public Worker() {
  6. product = new Product();
  7. }
  8. @Override
  9. void builderA() {
  10. product.setBuildA("地基");
  11. System.out.println("地基");
  12. }
  13. @Override
  14. void builderB() {
  15. product.setBuildB("钢筋工程");
  16. System.out.println("钢筋工程");
  17. }
  18. @Override
  19. void builderC() {
  20. product.setBuildC("铺电缆");
  21. System.out.println("铺电缆");
  22. }
  23. @Override
  24. void builderD() {
  25. product.setBuildD("粉刷");
  26. System.out.println("粉刷");
  27. }
  28. @Override
  29. Product getProduct() {
  30. return product;
  31. }
  32. }
  1. package model.factory.builder;
  2. //指挥是核心,负责指挥构建一个工程,工程如何构建,由它决定
  3. public class Director {
  4. public Product build(Builder builder){
  5. //指挥工人按顺序建房子
  6. builder.builderA();
  7. builder.builderC();
  8. builder.builderD();
  9. builder.builderB();
  10. return builder.getProduct();
  11. }
  12. }
  1. package model.factory.builder;
  2. public class Test {
  3. public static void main(String[] args) {
  4. //指挥
  5. Director director = new Director();
  6. //指挥具体的工人完成产品
  7. //输出:Produt{BuildA='地基', BuildB='钢筋工程', BuildC='铺电缆', BuildD='粉刷'}
  8. Product build = director.build(new Worker());
  9. System.out.println(build);
  10. }
  11. }

image.png

优点

可以切换类的构建顺序,灵活

缺点

客户就是Director,没有使用静态内部类的方式,显得僵硬了点

7、原型模式

浅拷贝

image.png

  1. package model.factory.prototype.demo1;
  2. import java.util.Date;
  3. public class Video implements Cloneable {
  4. private String name;
  5. private Date createTime;
  6. @Override
  7. public String toString() {
  8. return "Video{" +
  9. "name='" + name + '\'' +
  10. ", createTime=" + createTime +
  11. '}';
  12. }
  13. @Override
  14. protected Object clone() throws CloneNotSupportedException {
  15. return super.clone();
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. public Date getCreateTime() {
  24. return createTime;
  25. }
  26. public void setCreateTime(Date createTime) {
  27. this.createTime = createTime;
  28. }
  29. public Video(String name, Date createTime) {
  30. this.name = name;
  31. this.createTime = createTime;
  32. }
  33. public Video() {
  34. }
  35. }
  1. package model.factory.prototype.demo1;
  2. import java.util.Date;
  3. public class Test01 {
  4. public static void main(String[] args) throws CloneNotSupportedException {
  5. Date date = new Date();
  6. Video v1 = new Video("up主", date);
  7. Video v2 = (Video) v1.clone();
  8. System.out.println(v1);
  9. System.out.println(v1.hashCode());
  10. System.out.println("========================");
  11. System.out.println(v2);
  12. System.out.println(v2.hashCode());
  13. }
  14. }

深拷贝

image.png

  1. package model.factory.prototype.demo2;
  2. import java.util.Date;
  3. public class Video implements Cloneable {
  4. private String name;
  5. private Date createTime;
  6. @Override
  7. public String toString() {
  8. return "Video{" +
  9. "name='" + name + '\'' +
  10. ", createTime=" + createTime +
  11. '}';
  12. }
  13. @Override
  14. protected Object clone() throws CloneNotSupportedException {
  15. Object obj = super.clone();
  16. Video v = (Video) obj;
  17. v.createTime = (Date) this.createTime.clone();
  18. return obj;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public Date getCreateTime() {
  27. return createTime;
  28. }
  29. public void setCreateTime(Date createTime) {
  30. this.createTime = createTime;
  31. }
  32. public Video(String name, Date createTime) {
  33. this.name = name;
  34. this.createTime = createTime;
  35. }
  36. public Video() {
  37. }
  38. }
  1. package model.factory.prototype.demo2;
  2. import java.util.Date;
  3. public class Test02 {
  4. public static void main(String[] args) throws CloneNotSupportedException {
  5. Date date = new Date();
  6. Video v1 = new Video("up主", date);
  7. Video v2 = (Video) v1.clone();
  8. System.out.println(v1);
  9. System.out.println(v2);
  10. System.out.println("========================");
  11. date.setTime(21123281);
  12. System.out.println(v1);
  13. System.out.println(v2);
  14. }
  15. }

8、适配器模式

继承方式

image.png

  1. package model.adapter;
  2. //网线,用来上网
  3. public class Adaptee {
  4. public void request(){
  5. System.out.println("网线可以用来上网");
  6. }
  7. }
  1. package model.adapter;
  2. //适配器接口,可以造很多种适配器
  3. public interface NetToUsb {
  4. public void handleRequest();
  5. }
  1. package model.adapter;
  2. public class Adapt extends Adaptee implements NetToUsb {
  3. @Override
  4. public void handleRequest() {
  5. super.request();
  6. }
  7. }
  1. package model.adapter;
  2. public class Computer {
  3. public void net(NetToUsb adapt){
  4. //上网的具体实现
  5. adapt.handleRequest();
  6. }
  7. public static void main(String[] args) {
  8. Computer computer = new Computer();
  9. Adapt adapt = new Adapt();
  10. Adaptee adaptee = new Adaptee();
  11. computer.net(adapt);
  12. }
  13. }

image.png

组合方式

image.png

  1. package model.adapter;
  2. //网线,用来上网
  3. public class Adaptee {
  4. public void request(){
  5. System.out.println("网线可以用来上网");
  6. }
  7. }
  1. package model.adapter;
  2. //适配器接口,可以造很多种适配器
  3. public interface NetToUsb {
  4. public void handleRequest();
  5. }
  1. package model.adapter;
  2. //继承和组合。继承是单继承,也称类适配器;常用的是组合,如下:
  3. public class Adapt2 implements NetToUsb{
  4. private Adaptee adaptee;
  5. public Adapt2(Adaptee adaptee) {
  6. this.adaptee = adaptee;
  7. }
  8. @Override
  9. public void handleRequest() {
  10. adaptee.request();
  11. }
  12. }
  1. package model.adapter;
  2. public class Computer {
  3. public void net(NetToUsb adapt){
  4. //上网的具体实现
  5. adapt.handleRequest();
  6. }
  7. public static void main(String[] args) {
  8. Computer computer = new Computer();
  9. Adaptee adaptee = new Adaptee();
  10. Adapt2 adapt2 = new Adapt2(adaptee);
  11. computer.net(adapt2);
  12. }
  13. }

image.png

9、桥接模式

image.png
image.png
image.png

  1. package model.bridge;
  2. //品牌用接口
  3. public interface Brand {
  4. void info();
  5. }
  1. package model.bridge;
  2. //联想品牌
  3. public class Lenovo implements Brand {
  4. @Override
  5. public void info() {
  6. System.out.print("联想");
  7. }
  8. }
  1. package model.bridge;
  2. //苹果品牌
  3. public class Apple implements Brand {
  4. @Override
  5. public void info() {
  6. System.out.print("苹果");
  7. }
  8. }
  1. package model.bridge;
  2. //抽象的电脑类型
  3. public abstract class Computer {
  4. //组合、品牌
  5. protected Brand brand;
  6. public Computer(Brand brand) {
  7. this.brand = brand;
  8. }
  9. public void info(){
  10. brand.info();//自带品牌
  11. }
  12. }
  13. class Desktop extends Computer{
  14. public Desktop(Brand brand) {
  15. super(brand);
  16. }
  17. @Override
  18. public void info() {
  19. super.info();
  20. System.out.print("台式机");
  21. }
  22. }
  23. class Laptop extends Computer{
  24. public Laptop(Brand brand) {
  25. super(brand);
  26. }
  27. @Override
  28. public void info() {
  29. super.info();
  30. System.out.print("笔记本");
  31. }
  32. }
  1. package model.bridge;
  2. public class Test {
  3. public static void main(String[] args) {
  4. //苹果笔记本
  5. Computer computer1 = new Laptop(new Apple());
  6. computer1.info();
  7. System.out.println();
  8. //联想台式机
  9. Computer computer2 = new Desktop(new Lenovo());
  10. computer2.info();
  11. }
  12. }

特点
避免使用继承而多使用组合。