一、概念

设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发 人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

一般指的设计模式都是狭义的设计模式,业界公认的(发表过论文,形成的著作),《设计模式》 有Gof 4人组,经过大量的总结,得出的一些通用的软件设计方法。总结起来有23种

经验: 所谓设计模式,都是翻来覆去使用封装 继承 多态。

二、设计模式的六大原则

1、开闭原则(Open Close Principle)
开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3、依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。
5、迪米特法则,又称最少知道原则(Demeter Principle)
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

补充
UML ( 同一建模语言 ) ,辅助软件设计,程序界的代码设计图。

三、设计模式

3.1 工厂模式

简单工厂模式,属于一种创建型设计模式,创建对象使用。通常是创建一个类体系(类家族)中的对象。个别类创建也不用设计模式了。

  1. package Factory;
  2. public class factory {
  3. public static void main(String[] args) {
  4. xifu x = xifuFactory.creatXifu("xijiao");//等于 xifuFactory.XX
  5. x.run();
  6. }
  7. }
  8. //工厂模式
  9. abstract class xifu{
  10. abstract void run();
  11. }
  12. class xijiao extends xifu{
  13. @Override
  14. void run() {
  15. System.out.println("洗脚的。。。");
  16. }
  17. }
  18. class anmo extends xifu{
  19. @Override
  20. void run() {
  21. System.out.println("按摩的。。。");
  22. }
  23. }
  24. class dabaojian extends xifu{
  25. @Override
  26. void run() {
  27. System.out.println("大保健。。。");
  28. }
  29. }
  30. //定义一个工厂类 用于创建对象
  31. class xifuFactory{
  32. public static final String XX="xijiao";
  33. public static final String XX1="anmo";
  34. public static final String XX2="dabaojian";
  35. public static xifu creatXifu(String xx){
  36. if (xx.equals(XX)) return new xijiao();
  37. if (xx.equals(XX1)) return new anmo();
  38. if (xx.equals(XX2)) return new dabaojian();
  39. return null;
  40. }
  41. }

3.2 单例模式

一般用 在资源文件加载
确保一个类的实例只有一个,任何时间任何位置,获得的该类实例总是同一个。
思路就是,先私有化构造器 , 再准备一个该类的实例,最后提供一个方法获得这个实例。

  1. class Cat {
  2. //声明一个实例(懒汉模式)
  3. private volatlie static Cat instance = null;
  4. //私有化构造器
  5. private Cat(){}
  6. //返回实例的方法
  7. public static synchronized Cat getInstance(){
  8. if( instance == null ){
  9. instance = new Cat();
  10. }
  11. return instance;
  12. }
  13. }
  14. //饿汉 天生线程安全 的
  15. class Dog {
  16. //声明一个本的唯一实例(饿汉模式)
  17. private static Dog instance = new Dog() ;
  18. //1。私有化构造器
  19. private Dog(){}
  20. //2. 提供一个返回实例的方法
  21. public static Dog getInstance(){
  22. return instance;
  23. }
  24. }
  25. public class Test {
  26. public static void main(String[] args) {
  27. Dog dog = Dog.getInstance();
  28. Dog dog2 = Dog.getInstance();
  29. System.out.println(dog==dog2);
  30. System.out.println("--------------------------");
  31. Cat c = Cat.getInstance();
  32. Cat d = Cat.getInstance();
  33. System.out.println( c.hashCode());
  34. System.out.println( d.hashCode());
  35. }
  36. }

3.3 观察者模式

这种模式,建立了一种事件机制,当前一个对象的状态发生改变,可以自动通知到,关注它的对象。比如多个用户订阅天气服务(主题),天气变化后都会收到通知。

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. //主题(天气)
  4. class Weather {
  5. //天气信息
  6. private String info;
  7. //维护一个订阅者列表
  8. private List<Observer> list = new ArrayList<>();
  9. public String getInfo() {
  10. return info;
  11. }
  12. public void setInfo(String info) {
  13. this.info = info;
  14. //主题发生变化,通知他们更新数据
  15. for (Observer observer : list) {
  16. observer.update();
  17. }
  18. }
  19. //注册观察者的方法
  20. public void add( Observer obj ){
  21. list.add(obj);
  22. }
  23. }
  24. /**
  25. * 观察者接口
  26. */
  27. public interface Observer {
  28. //同步更新数据的方法
  29. public void update();
  30. }
  31. //具体观察者
  32. class LDHObsever implements Observer{
  33. private Weather target;
  34. public LDHObsever(Weather target) {
  35. this.target = target;
  36. //把自己注册到观察者列表中
  37. target.add(this);
  38. }
  39. @Override
  40. public void update() {
  41. System.out.println("刘德华收到:最新天气数据:"+target.getInfo());
  42. }
  43. }
  44. //具体观察者
  45. class WBQObsever implements Observer{
  46. private Weather target;
  47. public WBQObsever(Weather target) {
  48. this.target = target;
  49. //把自己注册到观察者列表中
  50. target.add(this);
  51. }
  52. @Override
  53. public void update() {
  54. System.out.println("王宝强收到:最新天气数据:"+target.getInfo());
  55. }
  56. }
  57. public class Test {
  58. public static void main(String[] args) throws InterruptedException {
  59. //主题
  60. Weather weather = new Weather();
  61. WBQObsever obj1 = new WBQObsever(weather);
  62. LDHObsever obj2 = new LDHObsever(weather);
  63. weather.setInfo("阵雨");
  64. Thread.sleep(1000);
  65. weather.setInfo("小雨");
  66. Thread.sleep(1000);
  67. weather.setInfo("晴");
  68. }
  69. }

3.4 建造者模式

使用更简洁的方式创建对象,或者按照步骤依次初始化对象的模式。

  1. /**
  2. * 电脑
  3. */
  4. public class Computer {
  5. private String cpu;
  6. private String ram;
  7. private String power;
  8. private String disk;
  9. private String gpu;
  10. private Computer() {
  11. }
  12. private Computer(String cpu, String ram, String power, String disk, String gpu) {
  13. this.cpu = cpu;
  14. this.ram = ram;
  15. this.power = power;
  16. this.disk = disk;
  17. this.gpu = gpu;
  18. }
  19. public String getCpu() {
  20. return cpu;
  21. }
  22. public void setCpu(String cpu) {
  23. this.cpu = cpu;
  24. }
  25. public String getRam() {
  26. return ram;
  27. }
  28. public void setRam(String ram) {
  29. this.ram = ram;
  30. }
  31. public String getPower() {
  32. return power;
  33. }
  34. public void setPower(String power) {
  35. this.power = power;
  36. }
  37. public String getDisk() {
  38. return disk;
  39. }
  40. public void setDisk(String disk) {
  41. this.disk = disk;
  42. }
  43. public String getGpu() {
  44. return gpu;
  45. }
  46. public void setGpu(String gpu) {
  47. this.gpu = gpu;
  48. }
  49. @Override
  50. public String toString() {
  51. return "Computer{" +
  52. "cpu='" + cpu + '\'' +
  53. ", ram='" + ram + '\'' +
  54. ", power='" + power + '\'' +
  55. ", disk='" + disk + '\'' +
  56. ", gpu='" + gpu + '\'' +
  57. '}';
  58. }
  59. //内部类,构造对象的属性
  60. static class Builder{
  61. private String cpu;
  62. private String ram;
  63. private String power;
  64. private String disk;
  65. private String gpu;
  66. public Builder setCpu(String cpu) {
  67. this.cpu = cpu;
  68. return this;
  69. }
  70. public Builder setRam(String ram) {
  71. this.ram = ram;
  72. return this;
  73. }
  74. public Builder setPower(String power) {
  75. this.power = power;
  76. return this;
  77. }
  78. public Builder setDisk(String disk) {
  79. this.disk = disk;
  80. return this;
  81. }
  82. public Builder setGpu(String gpu) {
  83. this.gpu = gpu;
  84. return this;
  85. }
  86. //构造方法
  87. public Computer build(){
  88. Computer computer = new Computer( this.cpu,this.ram,this.power,this.disk,this.gpu );
  89. return computer;
  90. }
  91. }
  92. }
  93. class Test {
  94. public static void main(String[] args) {
  95. //缺点,参数多,顺序不好把握 ctl+p 提示参数
  96. //Computer computer = new Computer( "AMD36000","皇家戟3333","长城500","三星T9999","RTX3060");
  97. //驱缺点,语句多
  98. /*Computer obj = new Computer();
  99. obj.setCpu("IntelI90000K");
  100. obj.setDisk("西部数据X888");
  101. obj.setRam("七彩虹8GB");
  102. obj.setPower("长城4000");*/
  103. //优点,链式调用
  104. Computer computer = new Computer.Builder().
  105. setCpu("AMD").
  106. setRam("三星").
  107. setGpu("RTX1080ti").
  108. setDisk("西部数据").
  109. setPower("长城888").
  110. build();
  111. System.out.println(computer);
  112. }
  113. }

3.5 装饰模式

对现有类装饰( 增加能力 )

  1. /*
  2. 接口类
  3. */
  4. public interface IGirl {
  5. void cook();
  6. }
  7. /**
  8. * 女生:简单的girl
  9. */
  10. class SimpleGirl implements IGirl {
  11. public void cook(){
  12. System.out.println("做饭");
  13. }
  14. }
  15. /**
  16. * 装饰类,把目标对象添加跳舞功能
  17. */
  18. class SingGirl implements IGirl {
  19. //引入一个Girl
  20. private IGirl girl;
  21. public SingGirl(IGirl girl) {
  22. this.girl = girl;
  23. }
  24. @Override
  25. public void cook() {
  26. System.out.println("唱歌.....");
  27. girl.cook();
  28. }
  29. }
  30. /**
  31. * 装饰类,把目标对象添加跳舞功能
  32. */
  33. class DanceGirl implements IGirl {
  34. //引入一个Girl
  35. private IGirl girl;
  36. public DanceGirl(IGirl girl) {
  37. this.girl = girl;
  38. }
  39. @Override
  40. public void cook() {
  41. System.out.println("跳舞.....");
  42. girl.cook();
  43. }
  44. }
  45. public class Test {
  46. public static void main(String[] args) {
  47. DanceGirl girl = new DanceGirl( new SingGirl( new SimpleGirl() ));
  48. girl.cook();
  49. }
  50. }

3.6 代理模式

这种模式,解决的是,直接使用某些对象不方便时,或者通过更多增强功能的时候,使用它。

  1. //被代理父类
  2. /**
  3. * 售票大厅(抽象类)
  4. */
  5. public abstract class SalesCenter {
  6. public abstract void salesTickets();
  7. }

被代理类

  1. //被代理的类
  2. public class TrainSalesCenter extends SalesCenter{
  3. @Override
  4. public void salesTickets() {
  5. System.out.println("销售火车票.....");
  6. }
  7. }
  8. //被代理的类
  9. public class BusSalesCenter extends SalesCenter{
  10. @Override
  11. public void salesTickets() {
  12. System.out.println("销售汽车票.....");//业务代码
  13. }
  14. }

代理类

  1. //代理类,代理售票行为
  2. public class ProxySalesCenter extends SalesCenter {
  3. //引入被代理对象
  4. private SalesCenter salesCenter;
  5. //设置代理对象
  6. public void setSalesCenter(SalesCenter salesCenter) {
  7. this.salesCenter = salesCenter;
  8. }
  9. @Override
  10. public void salesTickets() {
  11. //增强功能
  12. System.out.println("销售彩票.....");
  13. //调用被代理对象的方法
  14. salesCenter.salesTickets();
  15. //增强功能
  16. System.out.println("销售香烟....");
  17. }
  18. }