.1
* IO流分类:
* 流向:
* 输入流
* 输出流
* 数据类型:
* 字节流
* 字节输入流
* 字节输出流
* 字符流
* 字符输入流
* 字符输出流
*
* 注意:一般我们在讨论IO的分类时,默认是按照数据类型分的。
*
* 字节流:
* 字节输入流 InputStream(抽象类)
* 字节输出流 OutputStream(抽象类)
* 字符流:
* 字符输入流 Reader
* 字符输出流 Writer
- 学习习惯:
- 字节流
- 字符流
-
2.2
-
- 需求:请用字节流往一个文本文件中写一句话:”helloworld”。
- 分析:
- 首先要知道是字节流
- 写数据我们就应该知道是字节输出流
- 所以最终选择了OutputStream
- 而OutputStream是抽象类,所以我们应该找其子类
- 文件这个单词是File,所以我们就大胆的猜测下:FileOutputStream存在否。
-
- 我们如何往一个文件写数据呢?
- 或者说就是字节输出流的操作步骤是什么呢?
- A:创建字节输出流对象
- B:调用写数据的方法
- C:释放资源
public class OutputStreamDemo {
public static void main(String[] args) throws IOException {
/**
* 怎么使用文件输出流往文件中途写数据?
* 1.创建文件输出流对象
* 2.调用输出流对象的方法给文件中写数据
* 3.释放资源
*/
//public FileOutputStream(String name)
//public FileOutputStream(File file)
//创建文件输出流对象
FileOutputStream fos = new FileOutputStream("a.txt");
//public FileOutputStream(File file)
//File file = new File("a.txt");
//FileOutputStream fos = new FileOutputStream(file);
/**
* FileOutputStream fos = new FileOutputStream("a.txt");
* 做了那些事情?
* 1.创建fos对象指向文件a.txt
* 2.创建一个文件a.txt
*/
//调用输出流的写数据的方法给文件中写数据
//public void write(byte[] b)
byte[] byf = "helloworld".getBytes();
fos.write(byf);
//释放资源,关流操作
fos.close();
//关流之后,我们还能继续往文件中写数据码
//这样是不行的。。
//fos.write("java".getBytes());//java.io.IOException: Stream Closed
}
}
做法:
A: 两个构造的区别?
FileOutputStream(File file)
创建一个File对象,指向文件输出流;
FileOutputStream(String name)
创建一个具有文件名的输出流对象
FileOutputStream fos = new FileOutputStream(“fos.txt”);
请问上面这个操作做了哪几件事情?
* 1.创建了一个文件输出流fos,指向文件a.txt
* 2.创建了a.txt这个文件
B: fos.write(“helloworld”.getBytes());
C: fos.close();关流
D: fos.write(“java”.getBytes());
2.3
FileOutputStream 写数据的方法
write(byte[] b) :一次写入byte[]长度的字节
write(int b) :一次写一个字节
write(byte[] b, int off, int len) :一次写一个字节数组的一部分
2.4
字节输入流:
具体操作步骤:
* 字节输入流操作步骤:
* A:创建字节输入流对象
FileInputStream fis = new FileInputStream(“a.txt”);
B:调用方法读取数据
一次读取一个字节:read() – 读取不到内容的时候的返回值为 -1
(并且用循环改进)C:释放资源
fis.close练习:
- A:把a.txt的内容复制到b.txt中
C:把d:\复制视频文件
数据源:
- IODemo.java – 读取数据 – InputStream – FileInputStream – 一次读取一个字节
- 目的地:
- Copy.java – 写出数据 – OutputStream – FileOutputStream – 一次写一个字节
如果要复制文件的话:
前提要保证文件在该项目的根目录下;
要么就直接写该文件的绝对路径:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile {
public static void main(String[] args) throws IOException {
//A:把a.txt的内容复制到b.txt中
//封装数据源和目的地
FileInputStream fis = new FileInputStream("OutputStreamDemo.java");
FileOutputStream fos = new FileOutputStream("c.java");
//2.读取数据源中的数据,将读取到的数据写入目的地中
int by;
while ((by=fis.read())!=-1) {
//System.out.println(by);
//将读取到的字节写入fos中
fos.write(by);
}
//释放资源
fos.close();
fis.close();
}
}
复制视频文件
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMp4 {
public static void main(String[] args) throws IOException {
//1.疯转数据源和目的地
FileInputStream fis = new FileInputStream("D://b.mp4");
FileOutputStream fos = new FileOutputStream("d.mp4");
//2.读取数据源,写如目的地
int by;
while ((by=fis.read())!=-1) {
fos.write(by);
}
//3.释放资源
fos.close();
fis.close();
}
}
2.5
字节输入流:
具体操作步骤:
* 字节输入流操作步骤:
* A:创建字节输入流对象
FileInputStream fis = new FileInputStream(“a.txt”);
- B:调用方法读取数据(一次读取一个字节数组,提升效率)
一次读取一个字节数组: public int read(byte[] b):返回实际读取长度,数据被读取到数组中。
– 测试方法返回长度?根据String类的构造方法构造字符串 - C:释放资源
fis.close
(利用一次读写一个字节数组完成)
* 练习:
* A:把a.txt的内容复制到b.txt中
* C:把d:\复制视频文件
package cokm.edu_04;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMp4 {
public static void main(String[] args) throws IOException {
//一次读写一个字节数组
//1.封装数据源和目的地
FileInputStream fis = new FileInputStream("D://b.mp4");
FileOutputStream fos = new FileOutputStream("e.mp4");
//一次读写一个字节数组
byte[] bys = new byte[1024];
int len;
while ((len=fis.read(bys))!=-1) {
//读取多少就给fos中写多少数据
fos.write(bys, 0, len);
}
//释放资源
fos.close();
fis.close();
}
}
2.5
* 字节缓冲区流(也叫高效流):
- BufferedInputStream(read() 一次读取一个字节,
- public int read(byte[] b):返回实际读取长度,数据被读取到数组中。)
- BufferedOutputStream(write(byte[] b))
-
- 流
- 低级流: 基本的流,可以直接操作文件。
高级流:是操作基本流的流。
三:编码问题
String中的编码和解码问题。
-
- 编码:
- 把我们能够看懂的字符转换为看不懂的数据
- 解码:
- 把我们看不懂的数据转换为看得懂的字符
public byte[] getBytes(String charsetName) 按照给定的编码方式,编码字节数组(gbk,utf-8)
String(byte[] bytes, String charsetName) 按照给定的编码方式解码字符数组String s = "中国好"; byte[] bytes = s.getBytes("utf-8"); System.out.println(Arrays.toString(bytes)); //String(byte[] bytes, String charsetName) System.out.println(new String(bytes,"gbk"));
结论:用什么编码,就必须用什么解码。
否则会出现乱码四:字符流
Reader
Writer
1.1
* IO流中的编码和解码问题
* OutputStreamWriter:把字节输出流转换为字符输出流
* InputStreamReader:把字节输入流转换为字符输入流
1.2 转换流
写入数据,把字节输出流转换为字符输出流(不指定码表)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));
把字节输出流转换为字符输出流(指定码表)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8");
读取数据, 把字节输入流转换为字符输入流(不指定码表)
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
把字节输入流转换为字符输入流(指定码表)
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK");
总结:我们一般创建字符输入或者输出流一般情况下使用系统默认的码表就可以, 如果来来回回需要指定码表的话,就显得非常的麻烦了
1.3 (将以上创建方式继续简化)
* 如果采用刚才的方式,创建对象写起来比较复杂。
* InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));
* OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”));
* 为了简化这种操作,java就针对这两个转换的字符流提供其子类。
* FileReader
* FileWriter
* 它们的默认编码是采用系统编码。
构造学习:
FileWriter(File file)
FileWriter(String fileName)
FileReader(File file)
FileReader(String fileName)
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
/**
* 要给字符输出流中写数据步骤:
* 1.创建字符输出流对象,并指向一个文件
* 2.调用字符输出流写数据的方法给里面写数据
* 3.刷新缓冲区
* 4.关流
*/
// FileWriter(File file)
// FileWriter(String fileName)
//1.创建字符输出流对象
//FileWriter fw = new FileWriter(new File("c.txt"));
FileWriter fw = new FileWriter("c.txt");
//调用方法写数据
//一次写一个字符 write(int c)
//fw.write('a');
//一次写一个字符数组write(char[] cbuf)
//char[] chs = {'h','e','l','l','o'};
//fw.write(chs);
//一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
//char[] chs = {'h','e','l','l','o'};
//fw.write(chs, 2, 3);
//一次写一个字符串write(String str)
//fw.write("helloworld");
//一次写一个字符串的一部分write(String str,int off,int len)
fw.write("helloworld", 5, 5);
//刷新缓冲区
fw.flush();
//关流
fw.close();
}
}
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
* FileReader(File file)
FileReader(String fileName)
*
*/
public class FileReaderDemo {
public static void main(String[] args) throws Exception {
/**
* 使用字符输入流读取c.txt真的个文件的步骤:
* 1.创建字符输入流对象,指向c.txt这个文件
* 2.一次读取一个字符
* 3.关流
*/
//1.创建字符输入流对象,指向c.txt这个文件
FileReader fr = new FileReader("c.txt");
//2.一次读取一个字符
/*System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println(fr.read());*/
//使用循环改进
/* int ch;
while ((ch=fr.read())!=-1) {
System.out.println((char)ch);
}*/
//一次读取一个字符数组
/* char[] chs = new char[2];
System.out.println(fr.read(chs));//一次读取一个字符数组,返回的是读取到的实际的字符长度
System.out.println(fr.read(chs));
System.out.println(fr.read(chs));
System.out.println(fr.read(chs));
System.out.println(fr.read(chs));*/
//使用循环改进上面代码
//定义一个字符数组
char[] chs = new char[1024];
int len;
while ((len=fr.read(chs))!=-1) {
System.out.println(new String(chs, 0, len));
}
//3.关流
fr.close();
}
}
* flush()和close()的区别?
* A:flush 刷新缓冲区,流对象可以继续
* B:close 先刷新缓冲区,再关闭流对象。流对象不可以继续使用了。
练习:给字符输出流里面利用方法写数据
* 字符输出流操作步骤:
* A:创建字符输出流对象
* B:调用写数据方法
* C:释放资源
*
* 写数据方法:
* 一次写一个字符 write(int c)
* 一次写一个字符数组write(char[] cbuf)
* 一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
* 一次写一个字符串write(String str)
* 一次写一个字符串的一部分write(String str,int off,int len)
1.4 字符输入流
* 字符输入流操作步骤:
* A:创建字符输入流对象
FileReader fr = new FileReader(“a.txt”);
B:读取数据并显示在控制台
a:一次读取一个字符
一次读取一个字符
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}*b:一次读取一个字符数组
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}- C:释放资源
fr.close();
- C:释放资源
注意:字符流输入输出流复制的文件是有要求的,简单来说只要是记事本打开文件的内容你能够看得懂,
就可以用字符流来进行复制,否则不行
具体原因:像复制MP3或者一些视频文件的时候,如果他的字节个数不是偶数的话,就会造成文件的缺损,因为一个字符等于两个字节
1.利用字符流复制java文件(两种方式,一次读写一个字符,一次读写一个字符数组)
public class CopyFile {
public static void main(String[] args) throws IOException {
/**
* 1.封装数据源和目的地
* 2.一次读写一个字符或者一次读写一个字符数组
* 3.关流
*/
//1.封装数据源和目的地
FileReader fr = new FileReader("InputStreamReaderDemo.java");
FileWriter fw = new FileWriter("d.java");
//2.1一次读写一个字符
/*int ch;
while ((ch=fr.read())!=-1) {
fw.write(ch);//一次写一个字符
fw.flush();//每写一次刷新缓冲区
}*/
//2.2一次读写一个字符数组
char[] chs = new char[1024];
int len;
while ((len=fr.read(chs))!=-1) {
fw.write(chs, 0, len);
fw.flush();
}
//3.关流
fw.close();
fr.close();
}
}
1.6 高效流:操作基本流的流
需求:
* 需求:
* 给文件中写入十个”helloworld”,每写一个换一行,每写一行必须写入一个换行符“/r/n”
这样写的弊端,windows系统下的换行符是“/r/n”,Linux是”\n”,Mac是”\r”,这样会造成代码的通用性不强
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
* * BufferedWriter:字符缓冲输出流
构造:BufferedWriter(Writer out)
特殊方法:public void newLine():会根据系统来确定写入不同的换行符
*
*/
public class BufferedWriterDemo2 {
public static void main(String[] args) throws IOException {
//使用高效字符输出流写入10个helloworld,每写一个换一行
/**
* 1.创建字符高效输出流,并指向一个txt文件
* 2.调用里面写数据的方法,给文件中写入数据
* 3.调用换行的方法,给写入的数据换行
* 4.刷新换新区
* 5.关流
*/
//1.创建字符高效输出流,并指向一个txt文件
BufferedWriter bw = new BufferedWriter(new FileWriter("f.txt"));
//2.调用里面写数据的方法,给文件中写入数据
for (int i = 0; i < 10; i++) {
//给文件中写入helloworld
bw.write("helloworld");
//写入换行符
bw.newLine();
//刷新缓冲区
bw.flush();
}
//关流
bw.close();
}
}
BufferedReader:字符缓冲输入流
构造:BufferedReader(Reader in)
特殊方法:public String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null- BufferedWriter:字符缓冲输出流
构造:BufferedWriter(Writer out)
特殊方法:public void newLine():会根据系统来确定写入不同的换行符
- BufferedWriter:字符缓冲输出流
package com.edu_06;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
/**
* 需求:使用高效字符输入流读取f.txt文件
* 1.创建高效字符输入流对象,指向f.txt
* 2.一次读取一行,readLine()
* 3.关流
*/
//1.创建高效字符输入流对象,指向f.txt
//BufferedReader(Reader in)
BufferedReader br = new BufferedReader(new FileReader("f.txt"));
//2.一次读取一行,readLine(),当读取文件末尾的时候返回null
/* System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());*/
//使用循环改进
String line;
while ((line= br.readLine())!=null) {
System.out.println(line);
}
//3.关流
br.close();
}
}
最终练习:
* 复制文本文件:
* 4种
*
* 基本字符流一次读写一个字符
* 基本字符流一次读写一个字符数组
* 高效字符流一次读写一个字符
* 高效字符流一次读写一个字符数组
*
* 数据源:
* a.txt
* 目的地:
* b.txt
package com.edu_07;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
method();//基本字符流一次读写一个字符
method2();//基本字符流一次读写一个字符数组
method3();//高效字符流一次读写一个字符
method4();//高效字符流一次读写一个字符数组
}
private static void method4() throws IOException {
//高效字符流一次读写一个字符数组
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("j.txt"));
//一次读写一个字符数组
char[] chs = new char[1024];
int len;
while ((len = br.read(chs))!=-1) {
bw.write(chs, 0, len);
bw.flush();
}
//释放资源
bw.close();
br.close();
}
private static void method3() throws IOException {
//高效字符流一次读写一个字符
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("j.txt"));
//一次读写一个字符
int ch;
while ((ch=br.read())!=-1) {
bw.write(ch);
bw.flush();
}
//关流
bw.close();
br.close();
}
private static void method2() throws IOException {
//基本字符流一次读写一个字符数组
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("j.txt");
//一次读写一个字节数组
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs))!=-1) {
fw.write(chs, 0, len);
fw.flush();
}
//关流
fw.close();
fr.close();
}
private static void method() throws IOException {
//基本字符流一次读写一个字符
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("j.txt");
//一次读取一个字符,返回的是该字符对应的int值
/* System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
System.out.println((char)fr.read());
*/
int ch;
while ((ch=fr.read())!=-1) {
//System.out.println((char)ch);
fw.write(ch);
fw.flush();
}
//释放资源
fr.close();
fw.close();
}
}
1.7
BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
的特性。
1.需求:向文件中写入十个中国好,每写一个换一行(普通方式实现,高效流输出流特性实现)
package com.edu_08;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
//1.需求:向文件中写入十个中国好,每写一个换一行(高效流输出流特性实现)
//创建高效字符输出流对象,并指向ff.txt文件
BufferedWriter bw = new BufferedWriter(new FileWriter("ff.txt"));
//写入数据
for (int i = 0; i < 10; i++) {
/**
* 1.写一行
* 2.换行
* 3.刷新
*/
bw.write("中国好");
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
2.利用字符高效流的一次读写一行的特性复制文件
写数据注意三部曲:
bw.write(line);
bw.newLine();
bw.flush();
package com.edu_08;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.annotation.processing.Filer;
import javax.lang.model.element.Element;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileManager.Location;
/**
* 2.利用字符高效流的一次读写一行的特性复制文件
写数据注意三部曲:
bw.write(line);
bw.newLine();
bw.flush();
*
*/
public class Test {
public static void main(String[] args) throws IOException {
//封装数据源和目的地
BufferedReader br = new BufferedReader(new FileReader("InputStreamReaderDemo.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("copy.java"));
//读取一行写一行
String line;
while ((line = br.readLine())!=null) {
//System.out.println();
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
二:IO流练习
1.键盘录入数据并存储
* 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
*
* 分析:
* A:定义学生类
* B:创建集合,采用TreeSet集合,并按照比较器排序
* C:键盘录入5个学生信息并存入集合
* D:遍历集合,并把数据写到文本文件
创建一个学生的Javabean
package com.edu_09;
public class Student {
private String name;
private int chinese;
private int math;
private int english;
public Student(String name, int chinese, int math, int english) {
super();
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
//获取总成绩的方法
public int getAllScore(){
return chinese+math+english;
}
}
一个测试类:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/**
* 1.键盘录入数据并存储
* 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
*
* 分析:
* 1.创建学生类
* 2.键盘录入5个学生信息,并封装成学生对象,存储到TreeSet(使用比较器写一个排序算法)
* 3.遍历集合,将信息存储到文本文件中(BufferedWriter)
*/
public class StudentTest {
public static void main(String[] args) throws IOException {
//创建一个TreeSet集合,并写一个比较器
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAllScore() - s2.getAllScore();
int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//键盘录入5个学生信息
for (int i = 0; i < 5; i++) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//接受键盘录入数据
System.out.println("请输入你的姓名");
String name = sc.nextLine();
System.out.println("请输入你的语文成绩");
int chinese = sc.nextInt();
System.out.println("请输入你的数学成绩");
int math = sc.nextInt();
System.out.println("请输入你的英语成绩");
int english = sc.nextInt();
//封装成学生对象,存储集合
Student s = new Student(name, chinese, math, english);
ts.add(s);
}
System.out.println("数据录入完毕。。");
//遍历集合,将集合中的数据全取不出来之后写入文件中,每一个学生信息占一行
BufferedWriter bw = new BufferedWriter(new FileWriter("score.txt"));
for (Student s : ts) {
String info = s.getName()+" "+s.getChinese()+" "+s.getMath()+" "+s.getEnglish()+" "+s.getAllScore();
//将拼接成的字符串写入文件中
bw.write(info);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
三:设计模式
A:设计模式概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰.
B:设计模式分类
创建型模式(创建对象的): 单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
行为型模式(对象的功能): 适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
结构型模式(对象的组成): 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、
解释器模式、状态模式、策略模式、职责链模式、访问者模式。
单例设计模式(掌握)
A:单例设计思想
保证类在内存中只有一个对象
B:如何实现类在内存中只有一个对象呢?
构造私有
本身提供一个对象
通过公共的方法让外界访问
C: 单列模式分为 懒汉式和饿汉式
package com.edu_10;
public class SingleInstanceDemo {
/**
* 饿汉式:当这个类一被加载,就在内存中创建了一个对象
*
* 1.保证内存中只有一个对象(构造私有)
* 2.在本类中创建一个该类的对象
* 3.创建一个公共的访问方式给外界获取该对象
*/
private SingleInstanceDemo(){}
//静态的随着类的加载而加载
private static SingleInstanceDemo instance = new SingleInstanceDemo();
//给外界提供公共的访问方式,返回该对象
public static SingleInstanceDemo getInstance(){
return instance;
}
}
证明:
package com.edu_10;
public class SingleInstanceDemoTest {
public static void main(String[] args) {
SingleInstanceDemo instance = SingleInstanceDemo.getInstance();
SingleInstanceDemo instance2 = SingleInstanceDemo.getInstance();
System.out.println(instance==instance2);
}
}
public class SingleInstanceDemo2 {
/**
* 单例设计模式之懒汉式:
* 需要的时候才去创建对象,不需要的时候不创建
*/
private SingleInstanceDemo2(){}
private static SingleInstanceDemo2 instance = null;
public static SingleInstanceDemo2 getInstance(){
if (instance==null) {
instance = new SingleInstanceDemo2();
}
return instance;
}
}
证明:
package com.edu_10;
public class SingleInstanceDemo2Test {
public static void main(String[] args) {
SingleInstanceDemo2 instance = SingleInstanceDemo2.getInstance();
SingleInstanceDemo2 instance2 = SingleInstanceDemo2.getInstance();
System.out.println(instance==instance2);
}
}
工厂设计模式
A:简单工厂模式概述: 又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
B:优点: 使用静态工厂模式的优点是实现责任的分割,该模式的核心是工厂类,工厂类含有必要的选择逻辑,可以决定什么时候创建哪一个产品的实例,
而客户端则免去直接创建产品的责任,而仅仅是消费产品。也就是说静态工厂模式在不改变客户端代码的情况可以动态的增加产品。
明确了类的职责
C:缺点
这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,
就需要不断的修改工厂类,不利于后期的维护
A:工厂方法模式概述
工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。
B:优点
客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,
只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
C:缺点: 需要额外的编写代码,增加了工作量
package com.edu_12;
public abstract class Animal {
public abstract void eat();
}
public abstract class AnimalFactory {
//创建动物的功能
public abstract Animal getAnimal();
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class CatFactory extends AnimalFactory{
@Override
public Animal getAnimal() {
// TODO Auto-generated method stub
return new Cat();
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
public class DogFactory extends AnimalFactory{
@Override
public Animal getAnimal() {
// TODO Auto-generated method stub
return new Dog();
}
}
在之后要添加对象的时候:需要添加这个对象的工厂,然后再创建对象
public class TigerFactory extends AnimalFactory{
@Override
public Animal getAnimal() {
// TODO Auto-generated method stub
return new Tiger();
}
}
public class Tiger extends Animal{
@Override
public void eat() {
System.out.println("虎吃人");
}
}
public class Test {
public static void main(String[] args) {
//需要一个狗对象
AnimalFactory af = new DogFactory();
Animal a = af.getAnimal();
a.eat();
//需要一个猫对象
af = new CatFactory();
a = af.getAnimal();
a.eat();
//需要一个老虎类
af = new TigerFactory();
a = af.getAnimal();
a.eat();
}
}