【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<Weather> list=new ArrayList<Weather>();//程序的解耦
	//程序設計講究的是低耦合:類與類之間不要過分依賴
	//添加訂閱者
	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();
		
	}
}

基礎課程最後一天啦,接下來要開始做畢設啦,加油加油呀!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章