今日学习目标

  • 网络编程
  • TCP通信
  • Junit单元测试
  • 单列设计模式
  • 多列设计模式
  • 工厂设计模式

    1 网络编程

    1.1 网络编程三要素

  • IP地址 : 设备在网络中的地址,是唯一的标识。

  • 端口 : 设备在网络中的地址,是唯一的标识。
  • 数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。

    1.2 IP地址

  • P地址常见分类 : ipv4和ipv6

  • 常用命令:
    • ipconfig:查看本机IP地址
    • IP地址:检查网络是否连通
  • 特殊IP地址:
    • 127.0.0.1:是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
  • InetAddress类: | 构造方法 | 作用 | | —- | —- | | static InetAddress getByName(String host) | 在给定主机名的情况下确定主机的 IP 地址 | | String getHostName() | 获取此 IP 地址的主机名 | | String getHostAddress() | 返回 IP 地址字符串(以文本表现形式) |

1.3 端口

  • 端口:应用程序在设备中唯一的标识。
  • 端口号:用两个字节表示的整数,它的取值范围是0~65535,其中0~1023之间的端口号用于一些知名的网络服务或者应用,我们自己使用1024以上的端口号就可以了
  • 注意:一个端口号只能被一个应用程序使用

    1.4 通信协议

  • 协议:计算机网络中,连接和通信的规则被称为网络通信协议

  • UDP协议:
    • UDP是面向无连接通信协议.
    • 速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
  • TCP协议:

    • TCP协议是面向连接的通信协议
    • 速度慢,没有大小限制,数据安全

      2 TCP通信

      2.1 TCP发送数据

      ```java import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /* 客户端 : 发送数据的步骤 1 创建客户端的Socket对象 : Socket(String host, int port) 与指定服务端连接

      1. 参数说明:
      2. host 表示服务器端的主机名,也可以是服务器端的IP地址,只不过是String类型的
      3. port 表示服务器端的端口

      2 通获Socket对象取网络中的输出流,写数据

      1. OutputStream getOutputStream()

      3 释放资源

      1. void close()

    */ public class ClientDemo { public static void main(String[] args) throws IOException {

    1. // 创建客户端的Socket对象(Socket) 与指定服务端连接
    2. Socket socket = new Socket("127.0.0.1", 10010);
    3. // 通获Socket对象取网络中的输出流,写数据
    4. OutputStream os = socket.getOutputStream();
    5. os.write("hello".getBytes());
    6. // while(true){}
    7. // 释放资源
    8. os.close();
    9. socket.close();

    } } ```

    2.2 TCP接收数据

    ```java import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;

/* 服务端接收数据 :

  1. 1 创建服务器端的Socket对象 : ServerSocket
  2. ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号
  3. 2 监听客户端连接,并接受连接,返回一个Socket对象
  4. Socket accept() : 该方法会一直阻塞直到建立连接
  5. 3 获取网络中的输入流,用来读取客户端发送过来的数据
  6. InputStream getInputStream()
  7. 4 释放资源 : 服务端一般不会关闭
  8. void close()

*/ public class ServerDemo { public static void main(String[] args) throws IOException { // 1 创建服务器端的Socket对象 : ServerSocket类 // ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号 ServerSocket serverSocket = new ServerSocket(10010);

// 2 监听客户端连接,并接受连接,返回一个Socket对象 // Socket accept() : 该方法会一直阻塞直到建立连接 Socket socket = serverSocket.accept(); // // 3 获取网络中的输入流,用来读取客户端发送过来的数据 // InputStream getInputStream() InputStream is = socket.getInputStream(); int by; System.out.println(“read方法执行前”); while ((by = is.read()) != -1) { System.out.print((char) by); } System.out.println(“read方法执行后”); } }

  1. <a name="NyH7d"></a>
  2. #### 2.3 TCP练习1
  3. - 代码需要敲熟练:
  4. ```java
  5. public class ClientDemo {
  6. public static void main(String[] args) throws IOException {
  7. // 创建客户端的Socket对象(Socket) 与指定服务端连接
  8. Socket socket = new Socket("127.0.0.1", 10010);
  9. // 通获Socket对象取网络中的输出流,写数据
  10. OutputStream os = socket.getOutputStream();
  11. os.write("hello".getBytes());
  12. // 像服务端写入结束标记
  13. socket.shutdownOutput();
  14. BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  15. String line = br.readLine();
  16. System.out.println(line);
  17. // 释放资源
  18. br.close();
  19. os.close();
  20. socket.close();
  21. }
  22. }
  1. public class ServerDemo {
  2. public static void main(String[] args) throws IOException {
  3. // 1 创建服务器端的Socket对象 : ServerSocket类
  4. // ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号
  5. ServerSocket serverSocket = new ServerSocket(10010);
  6. // 2 监听客户端连接,并接受连接,返回一个Socket对象
  7. // Socket accept() : 该方法会一直阻塞直到建立连接
  8. Socket socket = serverSocket.accept();
  9. //
  10. // 3 获取网络中的输入流,用来读取客户端发送过来的数据
  11. // InputStream getInputStream()
  12. InputStream is = socket.getInputStream();
  13. int by;
  14. while ((by = is.read()) != -1) {
  15. System.out.print((char) by);
  16. }
  17. BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  18. bos.write("你谁啊");
  19. bos.close();
  20. is.close();
  21. socket.close();
  22. serverSocket.close();
  23. }
  24. }

2.4 TCP练习2

  1. public class ClientDemo {
  2. public static void main(String[] args) throws IOException {
  3. // 创建客户端Socket对象
  4. Socket socket = new Socket("127.0.0.1", 10086);
  5. BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg"));
  6. BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
  7. int by;
  8. while ((by = bis.read()) != -1) {// 从本地中读一个字节
  9. bos.write(by);// 往服务器写一个字节
  10. bos.flush();
  11. }
  12. // 写结束标记
  13. socket.shutdownOutput();
  14. // 把网络中的字节输入流 , 封装成高效的字符输入流
  15. BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  16. // String line;
  17. // while ((line = br.readLine()) != null) {
  18. // System.out.println(line);
  19. // }
  20. String msg = br.readLine();// 读到换行才叫读到一行, 所以必须写服务器必须写newLine
  21. System.out.println(msg);
  22. // 释放资源
  23. bis.close();
  24. socket.close();
  25. }
  26. }
  1. public class ServerDemo {
  2. public static void main(String[] args) throws IOException {
  3. // 创建服务端的连接对象
  4. ServerSocket serverSocket = new ServerSocket(10086);
  5. Socket socket = null;
  6. BufferedInputStream bis = null;
  7. BufferedWriter socketBw = null;
  8. while (true) {
  9. // 获取Socket对象
  10. socket = serverSocket.accept();
  11. // 获取网络中的字节输入流 在封装成高效的字节输入流对象
  12. bis = new BufferedInputStream(socket.getInputStream());
  13. // 创建本地的字节输出流 , 封装成高效的字节输出流
  14. BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("day13_demo\\图片\\a.jpg"));
  15. int by;
  16. while ((by = bis.read()) != -1) {
  17. bw.write(by);
  18. bw.flush();
  19. }
  20. //关闭本地流
  21. bw.close();
  22. // 获取网络中的字节输出流 , 封装成高效的字符输出流
  23. socketBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  24. socketBw.write("谢谢你");
  25. socketBw.newLine();// 必须有换行 , 因为readLine读到换行结束
  26. socketBw.flush();
  27. }
  28. // 释放资源
  29. // socketBw.close();
  30. // bis.close();
  31. // socket.close();
  32. // serverSocket.close();
  33. }
  34. }

2.5 TCP练习3

  1. public class ClientDemo {
  2. public static void main(String[] args) throws IOException {
  3. // 创建客户端Socket对象
  4. Socket socket = new Socket("127.0.0.1", 10086);
  5. BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg"));
  6. BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
  7. int by;
  8. while ((by = bis.read()) != -1) {// 从本地中读一个字节
  9. bos.write(by);// 往服务器写一个字节
  10. bos.flush();
  11. }
  12. // 写结束标记
  13. socket.shutdownOutput();
  14. // 把网络中的字节输入流 , 封装成高效的字符输入流
  15. BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  16. // String line;
  17. // while ((line = br.readLine()) != null) {
  18. // System.out.println(line);
  19. // }
  20. String msg = br.readLine();// 读到换行才叫读到一行, 所以必须写服务器必须写newLine
  21. System.out.println(msg);
  22. // 释放资源
  23. bis.close();
  24. socket.close();
  25. }
  26. }
  1. public class ServerDemo {
  2. public static void main(String[] args) throws IOException {
  3. // 创建服务端的连接对象
  4. ServerSocket serverSocket = new ServerSocket(10086);
  5. ExecutorService executorService = Executors.newFixedThreadPool(10);
  6. while (true) {
  7. // 获取Socket对象
  8. Socket socket = serverSocket.accept();
  9. executorService.submit(new ServerThread(socket));
  10. }
  11. // 释放资源
  12. // socketBw.close();
  13. // bis.close();
  14. // socket.close();
  15. // serverSocket.close();
  16. }
  17. }
  1. public class ServerThread implements Runnable {
  2. Socket socket = null;
  3. BufferedOutputStream bw = null;
  4. public ServerThread(Socket socket) {
  5. this.socket = socket;
  6. }
  7. @Override
  8. public void run() {
  9. try {
  10. // 获取网络中的字节输入流 在封装成高效的字节输入流对象
  11. BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
  12. // 创建本地的字节输出流 , 封装成高效的字节输出流
  13. bw = new BufferedOutputStream(new FileOutputStream("day13_demo\\图片\\" + UUID.randomUUID() + ".jpg"));
  14. int by;
  15. while ((by = bis.read()) != -1) {
  16. bw.write(by);
  17. bw.flush();
  18. }
  19. // 获取网络中的字节输出流 , 封装成高效的字符输出流
  20. BufferedWriter socketBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  21. socketBw.write("谢谢你");
  22. socketBw.newLine();// 必须有换行 , 因为readLine读到换行结束
  23. socketBw.flush();
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. } finally {
  27. //关闭本地流
  28. try {
  29. bw.close();
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }
  35. }

3 Junit单元测试

3.1 Junit4单元测试概述

  • 单元测试就是编写测试代码,可以准确、快速地保证程序的正确性,Junit是Java单元测试的框架
  • JUnit4可以通过注解的方式来标记方法 , 让方法存某种意义 ,常见的注解有:

    • @BeforeClass 全局只会执行一次,而且是第一个运行(标记的方法需要是一个静态无参无返回值方法)
    • @Before 在测试方法运行之前运行(非静态无参无返回值方法)
    • @Test 测试方法(此方法必须是非静态无参无返回值方法), 主要用于测试的方法
    • @After 在测试方法运行之后运行(非静态无参无返回值方法)
    • @AfterClass 全局只会执行一次,而且是最后一个运行(标记的方法需要是一个静态无参无返回值方法)
    • @Ignore 忽略此方法

      3.2 Junit的基本使用

  • 生成Junit测试框架

    • 右键选择 Generate(Alt+Insert)/ go to 选项 , 选择Test…
  • 可以在注释后面给个毫秒值单位

    • @Test(timeout = 1000)

      3.3 断言

  • 预先判断某个条件一定成立,如果条件不成立,则直接报错。

  • 使用 :
  • 格式:Assert.assertEquals(期望值,实际值) ```java //第一个参数表示期望值 //第二个参数表示实际值 // 如果实际值和期望值相同,说明结果正确就测试通过,如果不相同,说明结果是错误的,就会报错 Assert.assertEquals( 期望值, 实际值); Assert.assertEquals(“异常原因”, 期望值, 实际值);

//例如: int result = add(100,200); Assert.assertEquals(300, result);

  1. <a name="Ox6YD"></a>
  2. ### 4 单例设计模式
  3. <a name="gxcvi"></a>
  4. #### 4.1 单例设计模式的作用
  5. - 一个类只有一个对象实例。
  6. - 可以节省内存,共享数据
  7. <a name="NdFyq"></a>
  8. #### 4.2 单例设计模式的类型
  9. - 饿汉单例设计模式
  10. - 懒汉单例设计模式
  11. <a name="pRpky"></a>
  12. #### 4.3 实现单例模式的步骤
  13. - 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  14. - 在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
  15. - 定义一个静态方法返回这个唯一对象。
  16. <a name="mU5fA"></a>
  17. #### 4.3 饿汉单例设计模式
  18. - 饿汉单例设计模式就是使用类的时候已经将对象创建完毕
  19. ```java
  20. public class Singleton {
  21. // 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  22. private Singleton() {}
  23. // 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量。
  24. private static final Singleton instance = new Singleton();
  25. // 3.定义一个静态方法返回这个唯一对象。
  26. public static Singleton getInstance() {
  27. return instance;
  28. }
  29. }

4.4 懒汉单例设计模式

  • 懒汉单例设计模式就是调用getInstance()方法时对象才被创建

    1. public class Singleton {
    2. // 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
    3. private Singleton() {}
    4. // 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
    5. private static Singleton instance; // 0x001
    6. // 3.定义一个静态方法返回这个唯一对象。要用的时候才例化出对象
    7. public static synchronized Singleton getInstance() {
    8. if(instance == null) {
    9. instance = new Singleton();
    10. }
    11. return instance;
    12. }
    13. }
  • 注意事项:

    • 懒汉单例设计模式在多线程情况下可能会实例化出多个对象,不能保证单列状态,所以加上关键字synchronized,保证同步安全

      5 多例设计模式

      5.1 多例设计模式的作用

  • 通过多例模式可以保证项目中,应用该模式的类有固定数量的实例

  • 多例类要自我创建并管理自己的实例,还要向外界提供获取本类实例的方法。
  • 使用场景:线程池:
    • Executors.newFixedThreadPool(3);

      5.2.实现步骤

  1. 创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象
  2. 在类中定义该类被创建对象的总数量
  3. 在类中定义存放类实例的list集合
  4. 在类中提供静态代码块,在静态代码块中创建类的实例
  5. 提供获取类实例的静态方法

    5.3.实现代码

    ```java /* 需求 : 某一个学科有固定3位老师,年级中上该课程的老师就是这三位老师其中一位

    1. 要求使用多例模式 ,每次获取的都是这三位老师其中一位

    实现步骤 :

    1. 1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
    2. 2.在类中定义该类被创建对象的总数量
    3. 3.在类中定义存放类实例的list集合
    4. 4.在类中提供静态代码块,在静态代码块中创建类的实例
    5. 5.提供获取类实例的静态方法

    */ public class Teacher { // 1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。 private Teacher() { }

    // 2.在类中定义该类被创建对象的总数量 private static int maxCount = 3;

    // 3.在类中定义存放类实例的list集合 private static ArrayList list = new ArrayList<>();// {teacher1 , teacher2 , teacher3}

    // 4.在类中提供静态代码块,在静态代码块中创建类的实例 static {

    1. for (int i = 0; i < maxCount; i++) {
    2. list.add(new Teacher());
    3. }

    }

    // 5.提供获取类实例的静态方法 public static Teacher getInstance() {

    1. int index = new Random().nextInt(3);// [0 - 2]
    2. return list.get(index);

    }

}

  1. <a name="IMfWZ"></a>
  2. ### 6 工厂设计模式
  3. <a name="SxkEX"></a>
  4. #### 6.1 概述
  5. - 工厂模式:它提供了一种创建对象的最佳方式。之前我们创建类对象时, 都是使用 new 对象的形式创建, 除new 对象方式以外, 工厂模式也可以创建对象.
  6. <a name="jmx9L"></a>
  7. #### 6.2 作用
  8. - 解决类与类之间的耦合问题,防止因为对象的改变而影响到其他调用这个对象的类
  9. <a name="YIh3f"></a>
  10. #### 6.3案例实践
  11. ```java
  12. /*
  13. - 需求:定义汽车工厂类,生产各种品牌的车
  14. - 实现步骤
  15. - 编写一个Car接口, 提供run方法
  16. - 编写一个Falali类实现Car接口,重写run方法
  17. - 编写一个Benchi类实现Car接口
  18. =============================================
  19. - 提供一个CarFactory(汽车工厂),用于生产汽车对象
  20. - 定义CarFactoryTest测试汽车工厂
  21. */
  22. public class CarTest {
  23. public static void main(String[] args) {
  24. Car benchi = CarFactory.getInstance(Brand.BENCHI);
  25. System.out.println(benchi);
  26. }
  27. }
  28. // 汽车接口
  29. interface Car {
  30. public abstract void run();
  31. }
  32. // 编写一个Falali类实现Car接口,重写run方法
  33. class Falali implements Car {
  34. public Falali() {
  35. }
  36. @Override
  37. public void run() {
  38. System.out.println("法拉利破百需要3秒...");
  39. }
  40. }
  41. // 编写一个Benchi类实现Car接口
  42. class Benchi implements Car {
  43. @Override
  44. public void run() {
  45. System.out.println("奔驰破百需要5秒...");
  46. }
  47. }
  48. // 汽车品牌枚举
  49. enum Brand {
  50. BENCHI, FALALI, BAOMA, BINLI, AODI;
  51. }
  52. // 提供一个CarFactory(汽车工厂),用于生产汽车对象
  53. class CarFactory {
  54. private CarFactory() {
  55. }
  56. public static Car getInstance(Brand brand) {
  57. switch (brand) {
  58. case FALALI:
  59. return new Falali();
  60. case BENCHI:
  61. return new Benchi();
  62. default:
  63. return null;
  64. }
  65. }