day13-网络编程

今日目标

  • 网络编程
  • TCP通信
  • 单例设计模式
  • 多例设计模式
  • 工厂设计模式

1 网络编程

1.1 软件架构

  • C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件
  • B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等
  • 两种架构各有优势,但是都离不开网络的支持。网络编程 , 就是在一定的协议下,实现两台计算机的通信的程序
  • day12-网络编程 - 图1

1.2 什么是网络编程

  • 在网络通信协议下,不同计算机上运行的程序,可以进行数据传输

1.3 网络编程三要素

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

1.4 IP地址

  • IP:全称”互联网协议地址”,也称IP地址。是分配给上网设备的数字标签。常见的IP分类为:ipv4和ipv6
    简单来说 : 就是设备在网络中的唯一标识 , 想要连接哪一台电脑 , 就找到此电脑在网络中的ip地址

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

  • 常用命令:

    • ipconfig:查看本机IP地址
    • IP地址:检查网络是否连通
  • 特殊IP地址:

    • 127.0.0.1:是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
  • 为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress 供我们使用
    InetAddress:此类表示Internet协议(IP)地址

    • | static InetAddress getByName(String host) | 在给定主机名的情况下确定主机的 IP 地址 | | —- | —- | | String getHostName() | 获取此 IP 地址的主机名 | | String getHostAddress() | 返回 IP 地址字符串(以文本表现形式)。 |

1.5 端口

  • 端口:应用程序在设备中唯一的标识。

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

  • 注意:一个端口号只能被一个应用程序使用。

1.6 通信协议

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

    • 用户数据报协议(User Datagram Protocol)
    • UDP是面向无连接通信协议。
    • 速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
  • TCP协议

    • 传输控制协议 (Transmission Control Protocol)
    • TCP协议是面向连接的通信协议。
    • 速度慢,没有大小限制,数据安全

2 TCP通信

2.1 TCP发送数据

  1. package com.itheima.tcp_demo.demo1;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4. import java.net.Socket;
  5. /*
  6. 客户端 :
  7. 发送数据的步骤
  8. 1 创建客户端的Socket对象 : Socket(String host, int port) 与指定服务端连接
  9. 参数说明:
  10. host 表示服务器端的主机名,也可以是服务器端的IP地址,只不过是String类型的
  11. port 表示服务器端的端口
  12. 2 通获Socket对象取网络中的输出流,写数据
  13. OutputStream getOutputStream()
  14. 3 释放资源
  15. void close()
  16. */
  17. public class ClientDemo {
  18. public static void main(String[] args) throws IOException {
  19. // 创建客户端的Socket对象(Socket) 与指定服务端连接
  20. Socket socket = new Socket("127.0.0.1", 10010);
  21. // 通获Socket对象取网络中的输出流,写数据
  22. OutputStream os = socket.getOutputStream();
  23. os.write("hello".getBytes());
  24. // while(true){}
  25. // 释放资源
  26. os.close();
  27. socket.close();
  28. }
  29. }

2.2 TCP接收数据

  1. package com.itheima.tcp_demo.demo1;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. /*
  7. 服务端接收数据 :
  8. 1 创建服务器端的Socket对象 : ServerSocket类
  9. ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号
  10. 2 监听客户端连接,并接受连接,返回一个Socket对象
  11. Socket accept() : 该方法会一直阻塞直到建立连接
  12. 3 获取网络中的输入流,用来读取客户端发送过来的数据
  13. InputStream getInputStream()
  14. 4 释放资源 : 服务端一般不会关闭
  15. void close()
  16. */
  17. public class ServerDemo {
  18. public static void main(String[] args) throws IOException {
  19. // 1 创建服务器端的Socket对象 : ServerSocket类
  20. // ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号
  21. ServerSocket serverSocket = new ServerSocket(10010);
  22. // 2 监听客户端连接,并接受连接,返回一个Socket对象
  23. // Socket accept() : 该方法会一直阻塞直到建立连接
  24. Socket socket = serverSocket.accept();
  25. //
  26. // 3 获取网络中的输入流,用来读取客户端发送过来的数据
  27. // InputStream getInputStream()
  28. InputStream is = socket.getInputStream();
  29. int by;
  30. System.out.println("read方法执行前");
  31. while ((by = is.read()) != -1) {
  32. System.out.print((char) by);
  33. }
  34. System.out.println("read方法执行后");
  35. }
  36. }

2.3 TCP通信原理分析

day12-网络编程 - 图2

2.4 TCP三次握手

day12-网络编程 - 图3

2.5 TCP练习1

  1. package com.itheima.tcp_demo.test1;
  2. import java.io.*;
  3. import java.net.Socket;
  4. /*
  5. 客户端 :
  6. 发送数据的步骤
  7. 1 创建客户端的Socket对象 : Socket(String host, int port) 与指定服务端连接
  8. 参数说明:
  9. host 表示服务器端的主机名,也可以是服务器端的IP地址,只不过是String类型的
  10. port 表示服务器端的端口
  11. 2 通获Socket对象取网络中的输出流,写数据
  12. OutputStream getOutputStream()
  13. 3 释放资源
  14. void close()
  15. */
  16. public class ClientDemo {
  17. public static void main(String[] args) throws IOException {
  18. // 创建客户端的Socket对象(Socket) 与指定服务端连接
  19. Socket socket = new Socket("127.0.0.1", 10010);
  20. // 通获Socket对象取网络中的输出流,写数据
  21. OutputStream os = socket.getOutputStream();
  22. os.write("hello".getBytes());
  23. // 像服务端写入结束标记
  24. socket.shutdownOutput();
  25. BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  26. String line = br.readLine();
  27. System.out.println(line);
  28. // 释放资源
  29. br.close();
  30. os.close();
  31. socket.close();
  32. }
  33. }
  1. package com.itheima.tcp_demo.test1;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. /*
  6. 服务端接收数据 :
  7. 1 创建服务器端的Socket对象 : ServerSocket类
  8. ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号
  9. 2 监听客户端连接,并接受连接,返回一个Socket对象
  10. Socket accept() : 该方法会一直阻塞直到建立连接
  11. 3 获取网络中的输入流,用来读取客户端发送过来的数据
  12. InputStream getInputStream()
  13. 4 释放资源 : 服务端一般不会关闭
  14. void close()
  15. */
  16. public class ServerDemo {
  17. public static void main(String[] args) throws IOException {
  18. // 1 创建服务器端的Socket对象 : ServerSocket类
  19. // ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号
  20. ServerSocket serverSocket = new ServerSocket(10010);
  21. // 2 监听客户端连接,并接受连接,返回一个Socket对象
  22. // Socket accept() : 该方法会一直阻塞直到建立连接
  23. Socket socket = serverSocket.accept();
  24. //
  25. // 3 获取网络中的输入流,用来读取客户端发送过来的数据
  26. // InputStream getInputStream()
  27. InputStream is = socket.getInputStream();
  28. int by;
  29. while ((by = is.read()) != -1) {
  30. System.out.print((char) by);
  31. }
  32. BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  33. bos.write("你谁啊");
  34. bos.close();
  35. is.close();
  36. socket.close();
  37. serverSocket.close();
  38. }
  39. }

2.6 TCP练习2

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

2.7 TCP练习3

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

3 单例设计模式

学习目标

  • 能够使用单例设计模式设计代码

内容讲解

  • 正常情况下一个类可以创建多个对象
  1. public static void main(String[] args) {
  2. // 正常情况下一个类可以创建多个对象
  3. Person p1 = new Person();
  4. Person p2 = new Person();
  5. Person p3 = new Person();
  6. }
  • 如果说有时一个对象就能搞定的事情 , 非要创建多个对象 , 浪费内存!!!

3.1 单例设计模式的作用

  • 单例模式,是一种常用的软件设计模式。通过单例模式可以保证项目中,应用该模式的这个类只有一个实例。
    即一个类只有一个对象实例。

  • 好处 :可以节省内存,共享数据

3.2 单例设计模式实现步骤

  1. 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  2. 在该类内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量。
  3. 定义一个静态方法返回这个唯一对象。

3.3 单例设计模式的类型

根据创建对象的时机单例设计模式又分为以下两种:

  1. 饿汉单例设计模式

  2. 懒汉单例设计模式

=============================================================================================

3.4 饿汉单例设计模式

  • 饿汉单例设计模式就是使用类的时候已经将对象创建完毕
    不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故被称为“饿汉模式”。

  • 代码如下:

    1. public class Singleton {
    2. // 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
    3. private Singleton() {}
    4. // 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量。
    5. private static final Singleton instance = new Singleton();
    6. // 3.定义一个静态方法返回这个唯一对象。
    7. public static Singleton getInstance() {
    8. return instance;
    9. }
    10. }
  • 需求:定义一个皇帝类,要求对象只能存在一个。

    1. package com.itheima.singledesign;
    2. /*
    3. 需求 : 使用单例模式(饿汉式) , 要求此类只能有一个对象
    4. 步骤 :
    5. 1. 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
    6. 2. 在该类内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量。
    7. 3. 定义一个静态方法返回这个唯一对象。
    8. */
    9. public class King {
    10. // 1. 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
    11. private King(){}
    12. // 2. 在该类内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量。
    13. private static final King KING = new King();
    14. // 3. 定义一个静态方法返回这个唯一对象。
    15. public static King getInstance(){
    16. return KING;
    17. }
    18. }

=============================================================================================

3.5 懒汉单例设计模式

  • 懒汉单例设计模式就是调用getInstance()方法时对象才被创建
    也就是说先不急着实例化出对象,等要用的时候才实例化出对象。不着急,故称为“懒汉模式”。
    代码如下:

public class Singleton {

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

}

  1. - ##### 注意 :
  2. - 懒汉单例设计模式在多线程环境下可能会实例化出多个对象,不能保证单例的状态,所以加上关键字:synchronized,保证其同步安全。
  3. - 需求:使用懒汉单例 ,改写皇帝类的单例模式
  4. ```java
  5. package com.itheima.singledesign;
  6. /*
  7. 需求 : 使用单例模式(懒汉式) , 要求此类只能有一个对象
  8. 步骤 :
  9. 1. 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  10. 2. 在该类内部定义一个private static修饰的成员变量 . 此变量不需要赋值
  11. 3. 定义一个静态方法返回这个唯一对象。 此方法需要加上synchronized关键字保证在多线程中也只有一个实例对象
  12. */
  13. public class King2 {
  14. // 1. 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  15. private King2() {
  16. }
  17. // 2. 在该类内部定义一个private static修饰的成员变量 . 此变量不需要赋值
  18. private static King2 king;// null
  19. // 3. 定义一个静态方法返回这个唯一对象。 此方法需要加上synchronized关键字保证在多线程中也只有一个实例对象
  20. public static synchronized King2 getInstance() {
  21. if (king == null) {
  22. king = new King2();
  23. }
  24. return king;
  25. }
  26. }

知识小结

  • 单例模式可以保证系统中一个类只有一个对象实例。

  • 实现单例模式的步骤:

    • 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
    • 在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
    • 定义一个静态方法返回这个唯一对象。

4 多例设计模式

学习目标

  • 能使用多例设计模式设计代码

内容讲解

4.1 多例设计模式的作用

  • 多例模式,是一种常用的设计模式之一。通过多例模式可以保证项目中,应用该模式的类有固定数量的实例
    多例类要自我创建并管理自己的实例,还要向外界提供获取本类实例的方法。

  • 使用场景:线程池

    1. 线程池 = Executors.newFixedThreadPool(3);

4.2.实现步骤

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

4.3.实现代码

  • 某一个学科有固定3位老师,年级中上该课程的老师就是这三位老师其中一位
    要求使用多例模式 ,每次获取的都是这三位老师其中一位
  1. package com.itheima.moreinstance_demo;
  2. import com.itheima.homework.work.Student;
  3. import java.util.ArrayList;
  4. import java.util.Random;
  5. /*
  6. 需求 : 某一个学科有固定3位老师,年级中上该课程的老师就是这三位老师其中一位
  7. 要求使用多例模式 ,每次获取的都是这三位老师其中一位
  8. 实现步骤 :
  9. 1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  10. 2.在类中定义该类被创建对象的总数量
  11. 3.在类中定义存放类实例的list集合
  12. 4.在类中提供静态代码块,在静态代码块中创建类的实例
  13. 5.提供获取类实例的静态方法
  14. */
  15. public class Teacher {
  16. // 1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  17. private Teacher() {
  18. }
  19. // 2.在类中定义该类被创建对象的总数量
  20. private static int count = 3;
  21. // 3.在类中定义存放类实例的list集合
  22. private static ArrayList<Teacher> list = new ArrayList<>();
  23. // 4.在类中提供静态代码块,在静态代码块中创建类的实例
  24. static {
  25. for (int i = 0; i < count; i++) {
  26. list.add(new Teacher());
  27. }
  28. }
  29. // 5.提供获取类实例的静态方法
  30. public static Teacher getInstance() {
  31. int index = new Random().nextInt(count);// [0,3)
  32. return list.get(index);
  33. }
  34. }

4.4 小结

  • 多例模式作用 : 可以保证项目中一个类有固定个数的实例, 在实现需求的基础上, 能够提高实例的复用性.
    实现多例模式的步骤 :

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

5 工厂设计模式

学习目标

  • 能够使用工厂设计模式设计代码

内容讲解

5.1 概述

  • 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。之前我们创建类对象时, 都是使用 new 对象的形式创建, 除new 对象方式以外, 工厂模式也可以创建对象.

5.2 作用

  • 解决类与类之间的耦合问题

5.3案例实践

  • 需求:定义汽车工厂类,生产各种品牌的车

  • 实现步骤

    • 编写一个Car接口, 提供run方法
    • 编写一个Falali类实现Car接口,重写run方法
    • 编写一个Benchi类实现Car接口,重写run方法
    • 提供一个CarFactory(汽车工厂),用于生产汽车对象
    • 定义CarFactoryTest测试汽车工厂

实现代码

  1. package com.itheima.factorydesign_demo;
  2. /*
  3. - 需求:定义汽车工厂类,生产各种品牌的车
  4. - 实现步骤
  5. - 编写一个Car接口, 提供run方法
  6. - 编写一个Falali类实现Car接口,重写run方法
  7. - 编写一个Benchi类实现Car接口
  8. - 提供一个CarFactory(汽车工厂),用于生产汽车对象
  9. - 定义CarFactoryTest测试汽车工厂
  10. */
  11. public class CarTest {
  12. public static void main(String[] args) {
  13. Car car = CarFactory.getInstance(CarBrand.FALALI);
  14. car.run();
  15. }
  16. }
  17. // 定义车的品牌枚举
  18. enum CarBrand {
  19. // 枚举项
  20. FALALI, BENCHI, DAZHONG, BAOMA;
  21. }
  22. // 生产汽车对象的工厂
  23. class CarFactory {
  24. // 私有构造
  25. private CarFactory() {
  26. }
  27. public static Car getInstance(CarBrand brand) {
  28. switch (brand) {
  29. case FALALI:
  30. return new Falali(1);
  31. case BENCHI:
  32. return new Benchi();
  33. default:
  34. return null;
  35. }
  36. }
  37. }
  38. //// 生产汽车对象的工厂
  39. //class CarFactory {
  40. // // 私有构造
  41. // private CarFactory() {
  42. // }
  43. //
  44. // public static Car getInstance(String brand) {
  45. // switch (brand) {
  46. // case "Falali":
  47. // return new Falali(1);
  48. // case "Benchi":
  49. // return new Benchi();
  50. // default:
  51. // return null;
  52. // }
  53. // }
  54. //}
  55. // 编写一个Car接口, 提供run方法
  56. interface Car {
  57. public abstract void run();
  58. }
  59. class Falali implements Car {
  60. public Falali(int num) {
  61. }
  62. @Override
  63. public void run() {
  64. System.out.println("法拉利破百需要3秒!");
  65. }
  66. }
  67. class Benchi implements Car {
  68. @Override
  69. public void run() {
  70. System.out.println("奔驰破百需要5秒!");
  71. }
  72. }

知识小结

  • 工厂模式的存在可以改变创建对象的方式,降低类与类之间的耦合问题.