• java和设计模式(结构模式)


    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

            在设计模式中,有一类设计模式是比较有意思的,但是关注的人不多。这就是结构模式。如果说创建模式的重点是如何创建出实例对象,那么结构模式的特点就是利用类、示例构建更大的结构体。这听上去有点抽象,大家可以在实际开发中慢慢体会。这里面,最能体会这个观点的就是组合模式。组合模式类似于二叉树,二叉树的构成是树叶,树叶可以构建成树干,这样通过层层迭代,就可以进化成一个参天大树。

            常见的结构模式有7种,分别是代理模式、适配器模式、组合模式、外观模式、装饰器模式、享元模式和桥接模式

    1、代理模式

            代理模式比较简单,现实中也有这样的案例。比如开一个建筑公司来承揽工程,但是在这个领域开设公司是需要相关资质的。这个时候就有两种办法,一种办法就是公司自己去努力申请相关资质;另外一种就是公司将自己挂靠在某些有资质的公司上面,遇到不需要资质的项目就自己去独立完成,遇到有资质要求的工程,那只好转包给有资质条件的公司了。如果画一下图,可以这么来表示,

            将上述图形转成java代码,应该是这样的,

    1. import java.io.*;
    2. class Work
    3. {
    4. public void process()
    5. {
    6. return;
    7. }
    8. }
    9. class RealWork extends Work
    10. {
    11. @Override
    12. public void process()
    13. {
    14. System.out.println("RealWork");
    15. }
    16. }
    17. class ProxyWork extends Work
    18. {
    19. private Work s;
    20. public ProxyWork(Work w)
    21. {
    22. s = w;
    23. }
    24. @Override
    25. public void process()
    26. {
    27. if(null != s)
    28. {
    29. s.process();
    30. }
    31. System.out.println("ProxyWork");
    32. }
    33. }
    34. public class proxy
    35. {
    36. public static void main(String args[])
    37. {
    38. Work r = new RealWork();
    39. Work p = new ProxyWork(r);
    40. p.process();
    41. }
    42. }

    2、适配器模式

            适配器模式,大家可以和代理模式比较着来学习。在代理模式中,代理提供的接口和原来是一样的。而在适配器模式中,适配器的接口和原来是不一样的。同样以大家都熟悉的视频接口来说,一种老式的显示器接口是vga,这是很老的接口。但是现在笔记本电脑普遍都是usb接口、hdmi接口,所以这个时候如果需要把笔记本适配到老式的显示器上,只能借助于一个转换接口才能完美兼容老式的显示器。用一个类图可以这么来表示,

            将上述图形适当修改后,转成java代码,是这样的,

    1. import java.io.*;
    2. class vga
    3. {
    4. public void process()
    5. {
    6. System.out.println("vga interface");
    7. }
    8. }
    9. class hdmi2vga
    10. {
    11. public void work()
    12. {
    13. System.out.println("hdmi2vga");
    14. }
    15. }
    16. class hdmi extends vga
    17. {
    18. private hdmi2vga h;
    19. public hdmi()
    20. {
    21. h = new hdmi2vga();
    22. }
    23. @Override
    24. public void process()
    25. {
    26. System.out.println("hdmi interface");
    27. h.work();
    28. }
    29. }
    30. class minihdmi2vga
    31. {
    32. public void work()
    33. {
    34. System.out.println("minihdmi2vga");
    35. }
    36. }
    37. class minihdmi extends vga
    38. {
    39. private minihdmi2vga m;
    40. public minihdmi()
    41. {
    42. m = new minihdmi2vga();
    43. }
    44. @Override
    45. public void process()
    46. {
    47. System.out.println("minihdmi interface");
    48. m.work();
    49. }
    50. }
    51. public class adp
    52. {
    53. public static void main(String[] args)
    54. {
    55. vga h = new hdmi();
    56. h.process();
    57. vga m = new minihdmi();
    58. m.process();
    59. }
    60. }

    3、组合模式

            学习过数据结构的同学都知道二叉树。二叉树就是依靠一个又一个的节点搭建起来的。因此,学习过程中,完全可以用二叉树的思路来学习组合模式。类可以分成两种,一种是类似于叶子的子类,一种是需要子类构建的复合类,有点类似于树干,这样有了叶子和主干,就可以构建更大的类了。这听上去有点玄乎,实际上大家看一下类图,就不复杂了,

            上述图形转换成java代码后,是这样的,

    1. import java.io.*;
    2. class Node
    3. {
    4. public void display()
    5. {
    6. System.out.println("Node display");
    7. }
    8. }
    9. class Leaf extends Node
    10. {
    11. int num;
    12. public Leaf(int i)
    13. {
    14. num = i;
    15. }
    16. @Override
    17. public void display()
    18. {
    19. System.out.println("Leaf " + num + " display");
    20. }
    21. }
    22. class Trunk extends Node
    23. {
    24. private Node[] group = new Node[2];
    25. public Trunk(Node n1, Node n2)
    26. {
    27. group[0] = n1;
    28. group[1] = n2;
    29. }
    30. @Override
    31. public void display()
    32. {
    33. int i;
    34. for(i = 0; i < 2; i++)
    35. {
    36. group[i].display();
    37. }
    38. }
    39. }
    40. public class composite
    41. {
    42. public static void main(String[] args)
    43. {
    44. Node n1 = new Leaf(1);
    45. Node n2 = new Leaf(2);
    46. Node n3 = new Leaf(3);
    47. Node n4 = new Trunk(n2, n3);
    48. Node n5 = new Trunk(n1, n4);
    49. n5.display();
    50. }
    51. }

    4、外观模式

            外观模式有点类似于现在各个城市比较盛行的一站式窗口。之前去注册公司,可能需要分别去工商局、税务局、银行等机构逐一登记、申请。现在有了一站式中心后,这些都不要,我们所需要的就是提交材料,一站式中心对应的窗口会帮我们完成剩下来的所有工作。翻译成图形,就是这样的,

            上述图形转成java代码,是这样的,

    1. import java.io.*;
    2. class Shape
    3. {
    4. public void draw()
    5. {
    6. return;
    7. }
    8. }
    9. class Circle extends Shape
    10. {
    11. @Override
    12. public void draw()
    13. {
    14. System.out.println("Circle draw");
    15. }
    16. }
    17. class Rectangle extends Shape
    18. {
    19. @Override
    20. public void draw()
    21. {
    22. System.out.println("Rectangle draw");
    23. }
    24. }
    25. class Eclipse extends Shape
    26. {
    27. @Override
    28. public void draw()
    29. {
    30. System.out.println("Eclipse draw");
    31. }
    32. }
    33. public class shapeMaker
    34. {
    35. private Shape shapeCircle;
    36. private Shape shapeRect;
    37. private Shape shapeEclipse;
    38. public shapeMaker()
    39. {
    40. shapeCircle = new Circle();
    41. shapeRect = new Rectangle();
    42. shapeEclipse = new Eclipse();
    43. }
    44. public void drawCircle()
    45. {
    46. shapeCircle.draw();
    47. }
    48. public void drawRect()
    49. {
    50. shapeRect.draw();
    51. }
    52. public void drawEclipse()
    53. {
    54. shapeEclipse.draw();
    55. }
    56. public static void main(String[] args)
    57. {
    58. shapeMaker s = new shapeMaker();
    59. s.drawCircle();
    60. s.drawRect();
    61. s.drawEclipse();
    62. }
    63. }

    5、装饰器模式

            装饰器模式,主要就是希望在不改变现有接口的功能情况下,扩展出一些新的功能。比如说,我们设计一个绘图软件,之前可能只是绘制正方形、圆形接口。但是客户觉得太单调了,有要求,绘制有颜色的图形,比如说绿色的正方形、红色的圆形等等。因此,就应运而生了装饰器模式,

            上述图形,转成java代码后,是这样的,

    1. import java.io.*;
    2. class Shape
    3. {
    4. public void draw()
    5. {
    6. return;
    7. }
    8. }
    9. class Circle extends Shape
    10. {
    11. @Override
    12. public void draw()
    13. {
    14. System.out.println("Circle draw");
    15. }
    16. }
    17. class Rectangle extends Shape
    18. {
    19. @Override
    20. public void draw()
    21. {
    22. System.out.println("Rectangle draw");
    23. }
    24. }
    25. class Decorator extends Shape
    26. {
    27. private Shape shape;
    28. public Decorator(Shape s)
    29. {
    30. this.shape = s;
    31. }
    32. @Override
    33. public void draw()
    34. {
    35. shape.draw();
    36. }
    37. }
    38. class Decorator1 extends Decorator
    39. {
    40. public Decorator1(Shape s)
    41. {
    42. super(s);
    43. }
    44. @Override
    45. public void draw()
    46. {
    47. super.draw();
    48. System.out.println("Decorator1 draw");
    49. }
    50. }
    51. class Decorator2 extends Decorator
    52. {
    53. public Decorator2(Shape s)
    54. {
    55. super(s);
    56. }
    57. @Override
    58. public void draw()
    59. {
    60. super.draw();
    61. System.out.println("Decorator2 draw");
    62. }
    63. }
    64. public class DecoratorDemo
    65. {
    66. public static void main(String[] args)
    67. {
    68. Shape d1 = new Decorator1(new Circle());
    69. d1.draw();
    70. Shape d2 = new Decorator2(new Rectangle());
    71. d2.draw();
    72. }
    73. }

    6、享元模式

            这个中文翻译一直有点怪,其实英文叫flyweight,如果方便自己理解,也可以理解成lightweight。就是在有些场合,比如游戏界面,软件可能需要绘制很多很多的图像,这个时候就有可能需要实例化很多对象。但是,在这过程中不见得真的需要实例化每一种对象。此时,就可以本着用一种、注册一种的思路来解决这个问题。如果变成类图,就是这样的,

            上述图形,转成代码后,是这样的,

    1. import java.io.*;
    2. class shape
    3. {
    4. public void draw()
    5. {
    6. return;
    7. }
    8. }
    9. class circle extends shape
    10. {
    11. @Override
    12. public void draw()
    13. {
    14. System.out.println("circle draw");
    15. }
    16. }
    17. class shapeFactory
    18. {
    19. private shape[] group = {null, null, null, null, null};
    20. public shapeFactory()
    21. {
    22. return;
    23. }
    24. public void draw(int i)
    25. {
    26. if(i < 0 || i >= 5)
    27. {
    28. return;
    29. }
    30. if(group[i] == null)
    31. {
    32. group[i] = new circle();
    33. System.out.println("create circle " + i);
    34. }
    35. group[i].draw();
    36. System.out.println("finish draw " + i + "\n");
    37. }
    38. }
    39. public class flyweight
    40. {
    41. public static void main(String[] args)
    42. {
    43. shapeFactory s = new shapeFactory();
    44. s.draw(1);
    45. s.draw(4);
    46. s.draw(4);
    47. }
    48. }

     7、桥接模式

            之前装饰器模式,解决的是在不改变原有接口的基础上增加新功能的问题。而桥接模式,解决的是抽象和实现相分离的问题。比如不同的车有不同的功率,不同的男女有不同的职业,不同的户型有不同的面积,这里面就是一个m*n的关系。这个时候,用桥接模式就是比较适合的,因为两者的接口是完全分离开来的,

            上述图形转成java代码后,是这样的,

    1. import java.io.*;
    2. interface drawAPI
    3. {
    4. public void draw_circle(int x, int y, int radius);
    5. }
    6. class drawRedAPI implements drawAPI
    7. {
    8. @Override
    9. public void draw_circle(int x, int y, int radius)
    10. {
    11. System.out.println("draw red circle, " + "x = " + x + ", y = " + y);
    12. }
    13. }
    14. class drawGreenAPI implements drawAPI
    15. {
    16. @Override
    17. public void draw_circle(int x, int y, int radius)
    18. {
    19. System.out.println("draw green circle, " + "x = " + x + ", y = " + y);
    20. }
    21. }
    22. class shape
    23. {
    24. protected drawAPI d;
    25. public shape(drawAPI d)
    26. {
    27. this.d = d;
    28. }
    29. public void draw()
    30. {
    31. return;
    32. }
    33. }
    34. class circle extends shape
    35. {
    36. private int radius;
    37. private int x;
    38. private int y;
    39. public circle(int x, int y, int radius, drawAPI d)
    40. {
    41. super(d);
    42. this.x = x;
    43. this.y = y;
    44. this.radius = radius;
    45. }
    46. @Override
    47. public void draw()
    48. {
    49. d.draw_circle(x,y,radius);
    50. }
    51. }
    52. public class bridge
    53. {
    54. public static void main(String[] args)
    55. {
    56. shape s1 = new circle(1, 1, 2, new drawRedAPI());
    57. s1.draw();
    58. shape s2 = new circle(2, 3, 5, new drawGreenAPI());
    59. s2.draw();
    60. }
    61. }

    8、其他

            乱七八糟说了这么多,关键还是要用编程语言实现一把。不去实际操作一样,往往理解的不深刻。有的时候甚至要多次学习才能有一点收获,设计模式就是这样学习的。 

  • 相关阅读:
    C++模板编程与泛型编程之函数模板
    系统设计 - 我们如何通俗的理解那些技术的运行原理 - 第一部分:通信协议(1)
    Python抓取我的CSDN粉丝数,白嫖GithubAction自动抓取
    docker容器内缺少命令的解决办法
    优秀论文以及思路分析01
    PIR 传感器入侵检测算法和分析研究(Matlab代码实现)
    c++继承
    MySQL 快速入门之第一章 账号管理、建库以及四大引擎
    DCU集群搭建虚拟环境方法简介
    MyBatis3源码深度解析(十)MyBatis常用工具类(三)MetaObject&MetaClass
  • 原文地址:https://blog.csdn.net/feixiaoxing/article/details/125904320