【Java】day27--bat处理文件、懒汉单例设计模式的线程安全问题、反射、工厂设计模式、观察者设计模式部分知识点总结

(一)bat处理文件

bat处理文件
 jar文件双击运行仅对于图形化界面的程序起作用,对于控制台程序不起作用。
 bat批处理文件:bat批处理文件就是可以一次性执行多个命令的文件。
bat处理文件如何编写:
    新建一个记事本,修改后缀名为bat,把要执行的命令写到bat文件上。(右键编辑,双击不是打开,是运行里面的命令)
bat文件处理常用的命令:
    pause     让控制台停留。
    echo off  一个bat处理文件执行了echo off命令,那么echo off以下的命令都会隐藏起来,只显示结果
    @             隐藏当前行的命令
    title     设置控制台标题
    color     设置控制台的颜色
    rem             此命令后的字符为单行注释,不执行,和% %一样
    %1-%9             表示参数,变量

(二)懒汉单例设计模式的线程安全问题

单例设计模式:保证一个类在内存中只存在一个对象。
饿汉单例设计模式:
 懒汉单例设计模式:(存在一个线程安全问题)
     1.私有化构造函数
     2.声明本类的引用类型变量,但是不创建对象
     3.提供一个公共静态的方法获取本类的对象,获取之间先判断是否需已经创建了本类的
     对象,如果已经创建了直接返回即可,如果没有创建,把么先创建本类的对象,然后返回。

//懒汉单例设计模式(存在线程安全问题)
class Single{
	//声明本类的引用类型变量,但是不创建对象
	private static Single s=null;
	
	//私有化构造函数
	private Single() {}
	
	public static Single getInstance() {
		if(s==null) {//第二个之后的线程只需要判断s是否为空即可,不需要既判断锁的状态又判断s的状态
			synchronized ("锁") {
				if(s==null) {
					s=new Single();
				}//a13055958169  hqhqhqhq_
			}
		}
		return s;		
	}
}

(三)反射

反射:当一个class文件被加载到内存中时,jvm就会马上对该class文件的成员进行
           解剖,然后将class文件的成员数据装到一个Class对象中,如果可以获取到Class对象,
           就可以通过该Class对象来操作该类的所有成员。
注意:在反射技术中一个类的任何成员都使用了一个类来描述。

public class Person {
	String name;
	int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		
	}
	public void eat(int num,String[] arr) {
		System.out.println(name+"在吃第"+num+"碗饭...");
	}
	public static void sleep(int hours) {
		System.out.println("睡"+hours+"小时");
	}
	private void study() {
		System.out.println(name+"熬夜学习...");
	}
	@Override
	public String toString() {
		return "{姓名:"+this.name+" 年龄:"+this.age+"}";
	}
}


Class对象的获取方式:
    推荐使用:第一种。通过Class.forName获取Class对象。(字符串形式)
 

public static void main(String[] args) throws ClassNotFoundException {
		//方式1:通过Class.forName获取Class对象
		Class class1=Class.forName("reflect.Person");//完整包名+类名
	//	System.out.println("class1:"+class1.getSimpleName());
		//方式2:可以通过类名获取Class对象
		Class class2=Person.class;
		System.out.println("是一个对象么?"+(class1==class2));//Class对象只加载一次
		/*
		//方式3:可以通过对象获取Class对象
		Class class3=new Person().getClass();
		System.out.println("是同一个对象么?"+(class2==class3));//Class对象只加载一次
		*/
	}

通过Class对象获取构造方法:
Constructor 该类用于描述一个构造方法。

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//方式1:通过Class.forName获取Class对象
		Class class1=Class.forName("reflect.Person");//完整包名+类名
		//通过Class对象获取所有的构造方法
		/*
		//Constructor[] constructors=class1.getConstructors();//只获取了公共的构造方法
		Constructor[] constructors=class1.getDeclaredConstructors();//获取一个类的所有构造方法,包括私有的
		//增强for循环
		for(Constructor constructor:constructors) {
			System.out.println(constructor);
		}
		
		//获取单个构造方法,指定参数列表
		Constructor constructor=class1.getConstructor(String.class,int.class);
		//通过Constructor对象创建对象
		Person p=(Person)constructor.newInstance("大米",15);
		System.out.println(p);
		*/
		//获取私有的构造方法
		Constructor constructor=class1.getDeclaredConstructor(null);
		//设置构造方法的访问权限(暴力反射)
		constructor.setAccessible(true);
		Person p=(Person) constructor.newInstance(null);
		System.out.println(p);
	}

通过Class对象获取成员函数。--》Method类

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//获取Class对象
		Class class1=Class.forName("reflect.Person");
		//获取类所有的方法
		/*
		//Method[] methods=class1.getMethods();//获取所有公共的方法,包括继承(父类)的
		Method[] methods=class1.getDeclaredMethods();//获取所有的方法,包括私有的,但不包括继承的
		for(Method method:methods) {
			System.out.println(method);
		}
		*/
		//获取单个方法
		/*
		Method method=class1.getMethod("eat", int.class,String[].class);//第一个参数是函数名,第二个参数是形参列表,避免有方法重载
		//执行一个方法
		Person p=new Person("抹茶",18);
		method.invoke(p, 3,new String[]{"abc","aa","bb"});//第一个参数:方法的调用者对象,第二个参数:方法执行所需要的的参数
		//匿名数组对象
		
		Method method= class1.getMethod("sleep", int.class);
		method.invoke(null, 13);//静态方法不需要调用者对象
		*/
		//私有的方法
		Person p=new Person("抹茶",18);
		Method method= class1.getDeclaredMethod("study", null);
		//设置方法的访问权限是可以访问的
		method.setAccessible(true);
		method.invoke(p, null);
	}

通过Class对象获取一个类的成员变量--Field

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		//获取Class对象
		Class class1=Class.forName("reflect.Person");
		//获取该类所有的成员变量
		/*
		//Field[] fields=class1.getFields();//获取公共的
		Field[] fields=class1.getDeclaredFields();//获取非公共的
		for(Field field:fields) {
			System.out.println(field);
		}
		*/
		//获取某个非静态成员变量,非静态成员变量是对象的数据
		Person p=new Person("奶茶",22);
		Field nameField=class1.getDeclaredField("name");
		//给成员变量赋值
		nameField.set(p, "蛋糕");//第一个参数:对象 第二个参数:成员变量的值
		System.out.println(p);
	}

(四)工厂设计模式

工厂设计模式:专门用于生产对象的方法。

需求:定义一个工厂方法,可以产生任意类型的对象,产生的对象根据配置文件而定。
 

public static Object newInstance() throws Exception{
		BufferedReader bufferedReader=new BufferedReader(new FileReader("obj.txt"));
		//读取到完整的类名
		String className=bufferedReader.readLine();
		System.out.println(className);
		//根据类名获取Class对象
		Class class1=Class.forName(className);
		//获取无参的构造函数
		Constructor constructor=class1.getDeclaredConstructor(null);
		//通过无参的构造函数创建该类的对象
		Object o=constructor.newInstance(null);
		//读取配置文件,然后把对象的属性数据封装到对象中
		String line=null;
		while((line=bufferedReader.readLine())!=null) {
			String[] datas=line.split("=");
			//获取成员变量
			Field field=class1.getDeclaredField(datas[0]);
			field.setAccessible(true);
			//判断成员变量的数据类型
			if(field.getType()==int.class) {
				field.set(o, Integer.parseInt(datas[1]));//第一个参数:对象 第二个参数:属性值
			}else {
				field.set(o, datas[1]);
			}
		}
		return o;
	}
	public static void main(String[] args) throws Exception {
		Person p=(Person) newInstance();
		System.out.println("人对象:"+p);
	}

(五)观察者设计模式

观察者设计模式:
    当一个事物发生了指定动作时,要通知另外一个事物做出相应处理。
实现步骤:把要通知对方的行为抽取出来定义在一个接口上,然后再本类中维护该接口的成员。
需求:编写一个气象站,气象站要不断更新天气,人要根据当前天气做出相应的处理。
问题1:天气更新多次,人才做出一次反应。 随机数的原因。间隔时间随机。
     天气与人各自独立间隔时间进行更新,用多线程。
问题2:目前气象站只能为一个人工作。
    用容器存储人,使订阅者为多人工作。
问题3:在现实生活中,除了员工要关注天气以外,其他群体也要关注天气。
    订阅者都实现一个接口,就可以实现不同人群都可以关注天气。
 

//气象站
public class WeatherStation {
	String[] weathers= {"暴雨","雾霾","冰雹","台风","霜冻","晴天"};
	String currentWeather;//当前天气
	Random random=new Random();
	//容器存储天气订阅者
	ArrayList list=new ArrayList();//程序的解耦
	//程序设计讲究的是低耦合:类与类之间不要过分依赖
	//添加订阅者
	public void addListener(Weather w) {//
		list.add(w);
	}
	
	//气象站工作
	public void Work() throws Exception {
		new Thread() {
			@Override
			public void run() {
				while(true) {
					//每隔1-1.5秒更新一次天气
					updateWeather();
					//气象站更新天气之后就通知人(遍历)
					for(Weather w:list) {
						w.notifyWeather(currentWeather);
					}
					int millis=random.nextInt(501)+1000;
					try {
						Thread.sleep(millis);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}	
				}
			}
		}.start();//开启线程
	}
	//更新天气
	public void updateWeather() {
		int id=random.nextInt(weathers.length);
		currentWeather=weathers[id];
		System.out.println("当前天气是:"+currentWeather);
	}
}
//如果要订阅天气的群体必须要实现Weather接口
public interface Weather {
	//抽象方法
	public void notifyWeather(String weather);
}
public class Emp implements Weather{
	String name;

	public Emp(String name) {
		super();
		this.name = name;
	}
	//人要根据天气做出相应的处理方案
	public void notifyWeather(String weather) {
		//"暴雨","雾霾","冰雹","台风","霜冻","晴天"
		if("暴雨".equals(weather)) {
			System.out.println(name+"带着雨伞上班...");
		}else if("雾霾".equals(weather)) {
			System.out.println(name+"带着消毒面具上班...");
		}else if("冰雹".equals(weather)) {
			System.out.println(name+"带着头盔上班...");
		}else if("台风".equals(weather)) {
			System.out.println(name+"装着石头上班...");
		}else if("霜冻".equals(weather)) {
			System.out.println(name+"穿大棉袄上班...");
		}else if("晴天".equals(weather)) {
			System.out.println(name+"开开心心上班...");
		}
	}
}
public class Student implements Weather{
	String name;

	public Student(String name) {
		super();
		this.name = name;
	}
	public void notifyWeather(String weather) {
		//"暴雨","雾霾","冰雹","台风","霜冻","晴天"
		if("暴雨".equals(weather)) {
			System.out.println(name+"在宿舍休息!!!");
		}else if("雾霾".equals(weather)) {
			System.out.println(name+"霾太大,吸霾去!!!");
		}else if("冰雹".equals(weather)) {
			System.out.println(name+"冒着冰雹去上课...");
		}else if("台风".equals(weather)) {
			System.out.println(name+"装着石头上课...");
		}else if("霜冻".equals(weather)) {
			System.out.println(name+"穿大棉袄上课...");
		}else if("晴天".equals(weather)) {
			System.out.println(name+"教室睡觉...");
		}
	}
}
public class WeatherMain {
	public static void main(String[] args) throws Exception {
		//订阅者
		Emp emp1=new Emp("红豆");
		Emp emp2=new Emp("抹茶 ");
		Student s=new Student("小花");
		//气象站
		WeatherStation station=new WeatherStation();
		station.addListener(emp2);
		station.addListener(emp1);
		station.addListener(s);
		//气象站工作
		station.Work();
		
	}
}

基础课程最后一天啦,接下来要开始做毕设啦,加油加油呀!!!

你可能感兴趣的:(java)