UML图
**1、单向关联 **
实心单向箭头
2、双向关联
一条直线
3、自关联
实心单向箭头
4、聚合关系
空心菱形箭头 脱离可独立存在 菱形在整体处
5、组合关系
实心菱形箭头 脱离不可独立存在 菱形在整体处
6、依赖关系
某个方法局部变量、方法参数或对静态方法的调用来访问另一个类
虚线箭头指向被使用的类
7、继承关系
空心三角箭头指向父类
8、实现关系
空心虚线三角箭头指向接口
UML图
1、开闭原则
程序拓展时不能修改源代码 实现开闭原则需要使用接口和抽象类
2、里氏代换原则
子类可以拓展父类的功能,不能改变父类原有的功能
3、依赖倒转原则
要对抽象进行编程,不要对实现进行编程
4、接口隔离原则
客户端不应该被迫依赖于它不使用的方法 ; 一个类对另一个类的依赖应该建立在最小的接口上
5、迪米特法则
只和你的直接朋友交谈,不跟陌生人说话 如果有需求由第三方转发
例如粉丝见面会是跟经纪人直接对接而不是明星本人
6、合成复用原则
尽量先使用组合和聚合等关联关系来实现(耦合度低,可以在类的位置声明抽象),其次才考虑使用继承关系来实现
创建者模式
1、单例设计模式
该类负责创建自己的实例对象 且只能创建一个 还有一个返回实例对象的方法 如线程安全的懒汉式和饿汉式单例
/**
常用的静态内部类的懒汉单例模式 在没有添加任何锁的情况下保证了多线程下的安全,也能保证Singleton的唯一性
jvm在加载外部类时不会直接加载静态内部类
*/
public class StaticSingleton {
private StaticSingleton() {
}
//静态内部类
private static class SingletonHoloder{
private static final StaticSingleton INSTANCE = new StaticSingleton();
}
public StaticSingleton getInstance(){
return SingletonHoloder.INSTANCE;
}
}
/**
* 序列化 - 反序列化破坏单例 使用ObjectOutputStreeam的writeObject和ObjectInputStreeam的readObject
*/
public class Break {
public static void main(String[] args) throws Exception {
Break aBreak = new Break();
aBreak.writeObject2File();
aBreak.readObject2File();
aBreak.readObject2File();
}
//向文件中写数据(对象)
public void writeObject2File()throws Exception{
//获取Singleton对象
EagerSingleton instance = EagerSingleton.getInstance();
//创建对象输出流对象(new一个输出流)
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("C.txt"));
//writeObject方法中的对象需要序列化
outputStream.writeObject(instance);
outputStream.close();
}
//向文件中读数据(对象)
public void readObject2File() throws Exception {
//创建输入流对象
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("C.txt"));
//读取对象
EagerSingleton eagerSingleton = (EagerSingleton) objectInputStream.readObject();
System.out.println(eagerSingleton);
//释放资源
objectInputStream.close();
}
}
/**
* 反射破坏单例模式
*/
public class FanSheBreak {
public static void main(String[] args) throws Exception {
//获取EagerSingleton字节码对象(.class)
Class aClass = EagerSingleton.class;
//通过字节码对象的方法调用无参构造创建构造器对象
Constructor cons = aClass.getDeclaredConstructor();
//取消访问检查
cons.setAccessible(true);
//创建对象
StaticSingleton staticSingleton1 = (StaticSingleton) cons.newInstance();
StaticSingleton staticSingleton2 = (StaticSingleton) cons.newInstance();
System.out.println(staticSingleton1);
System.out.println(staticSingleton2);
}
}
/**
* 解决反射破坏单例模式
*/
private static boolean flag=false;
private StaticSingleton() {
//判断flag是否是true 则不是第一次访问 直接抛异常
if(flag){
throw new RuntimeException("不能创建多个对象");
}
flag=true;
}
/**
* InputStream:
*
* InputStream 是 Java 中用于读取原始字节数据的抽象基类。
* 它提供了读取字节数据的基本方法,如 read() 和 available()。
* InputStream 可以用于从各种数据源读取,例如文件、网络套接字或内存中的数据。
* InputStreamReader:
*
* InputStreamReader 是 Reader 类的子类,它充当字节流通向字符流的桥梁。
* 它使用指定的字符编码将 InputStream 中的字节数据转换为字符。
* InputStreamReader 通常用于将字节数据(如文件或网络流)转换为字符数据,以便进一步处理。
* BufferedReader:
*
* BufferedReader 是 Reader 类的子类,它提供了一种高效的方式来读取字符数据。
* 它使用内部缓冲区来减少实际的 I/O 操作次数,从而提高读取性能。
* BufferedReader 提供了 readLine() 方法,可以方便地逐行读取文本数据。
* 通常与 InputStreamReader 结合使用,以便从字节流中高效地读取字符数据。
* 以下是它们之间的区别的总结:
*
* 数据类型:InputStream 处理字节数据,而 InputStreamReader 和 BufferedReader 处理字符数据。
* 缓冲:InputStream 本身不提供缓冲功能,但 Java 中的 BufferedInputStream 可以提供。BufferedReader 内置了缓冲机制,可以提高读取效率。
* 编码转换:InputStreamReader 负责将字节转换为字符,需要指定字符编码。BufferedReader 通常读取已经转换为字符的 Reader 对象。
* 读取方式:InputStream 主要使用 read() 方法逐字节读取,而 BufferedReader 提供了 readLine() 方法,可以方便地逐行读取文本。
*/
public class RuntimeDemo {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
Process exec = runtime.exec("ipconfig");
// 使用BufferedReader来简化读取操作
BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream(), "GBK"));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
}