3、設計模式—單例、工廠、代理、介面卡、觀察者
1、 設計模式——單例模式
單例模式負責建立自己的物件,同時確保只有一個物件被建立。
比如,我們要統計網站的訪問使用者數,在任何時候都只有一個物件在記錄使用者數,否則就可能出現重複寫入的問題,這是單例模式應用的一個場景
實現如下
class Person{
//私有建構函式,組織物件例項化,從而阻止建立多個物件
private Person(){}
//私有物件變數
privatestatic Person p;
//在main函式執行前執行,產生一個例項物件
static{
p =new Person();
}
//獲取單例物件
publicstatic Person getPerson(){
if(p ==null){
p =new Person();
}
System.out.println("get single person object");
return p;
}
}
publicclass hello{
publicstaticvoid main(String args[]){
//獲取單例物件,並比較是否是同一個物件
Person p1 = Person.getPerson();
Person p2 = Person.getPerson();
if(p1 == p2){
System.out.println("is the same object"
}else{
System.out.println("is not the same object");
}
}
}
2、 設計模式——工廠模式
首先看下面程式碼,Apple和Orange實現了Fruit介面,程式要呼叫Apple的eat方法的話,要先在程式碼中顯示的例項化Apple類,才能呼叫
現在的問題是,如果我想要呼叫Orange的方法呢,這時就需要修改程式程式碼才能實現呼叫,這會非常麻煩,因為程式已經發布出去,你必須修改程式碼,再從新部署等等
interface Fruit{
publicvoid eat();
}
class Apple implements Fruit{
public
System.out.println("apple has been eat");
}
}
class Orange implements Fruit{
publicvoid eat(){
System.out.println("orange has been eat");
}
}
publicclass hello{
publicstaticvoid main(String args[]){
Fruit fruit =new Apple();
fruit.eat();
}
}
那有沒有什麼更簡單的方法呢?有,通過工廠模式,我們可以由類名來自動生成類的例項,再通過介面來呼叫例項中的方法即可。這樣如果我們要呼叫其它的類物件的方法,通過傳遞不同的類名作為引數就可以了,是不是簡單了很多,因為不要修改程式碼,也不需要重新部署等等,如下
interface Fruit{
publicvoid eat();
}
class Apple implements Fruit{
publicvoid eat(){
System.out.println("apple has been eat");
}
}
class Orange implements Fruit{
publicvoid eat(){
System.out.println("orange has been eat");
}
}
class Factory{
static Fruit getInstance(String className){
if("Apple".equals(className)){
returnnew Apple();
}
elseif("Orange".equals(className)){
returnnew Orange();
}
else{
returnnull;
}
}
}
publicclass hello{
publicstaticvoid main(String args[]){
Fruit fruit = Factory.getInstance("Orange");
fruit.eat();
}
}
3、 設計模式——代理模式
所謂代理模式,是指客戶端不直接呼叫實際的物件,而是通過呼叫代理物件來間接的呼叫實際的物件。
比如我要打官司,實際是我在打官司,但是現實中會通過律師來代理我來打官司,因為律師可以為我完成我不會或者無法完成的一些操作,比如填寫訴狀、起訴等操作
//起訴人介面
interface Plaintiff{
publicvoid sue();
}
//我是起訴人,要起訴xxx
class Me implements Plaintiff{
publicvoid sue(){
System.out.println("i will sue xxx");
}
}
//代理律師,起訴人通過代理律師來起訴,並且由代理律師填寫起訴書
class ProxyLayer implements Plaintiff{
private Plaintiff p;
//代理律師接受某起訴人的委託
public ProxyLayer(Plaintiff p){
this.p = p;
}
//律師填寫起訴書
publicvoid fillPlaint(){
System.out.println("the layer filled the plaint");
}
//代為起訴
publicvoid sue(){
this.fillPlaint();//填寫起訴書
this.p.sue();//代起訴人起訴
}
}
publicclass hello{
publicstaticvoid main(String args[]){
//我,委託代理律師
Plaintiff p =new ProxyLayer(new Me());
//進行起訴操作
p.sue();
}
}
4、 設計模式——介面卡模式
如果一個類要實現一個介面,則必須實現這個介面的所有方法,但是有時候一個介面定義了非常多的方法,而要實現的類又沒必要實現這麼多方法的時候怎麼辦呢?
這時候就可以使用介面卡模式,通過介面卡,我們可以將複雜的介面轉換成適合當前類的介面。
通過一個抽象類abstruct,先實現介面所有的方法(方法的實現為空),再由類來覆寫這個抽象類,這樣就實現了介面和類的適配
//汽車介面,有三個方法
interface Car{
publicvoid run();
publicvoid addOil();
publicvoid carry();
}
//汽車介面介面卡,實現了所有的汽車介面
abstractclass CarAdapter implements Car{
publicvoid run(){}
publicvoid addOil(){}
publicvoid carry(){}
}
//跑車沒有運載功能,通過介面卡實現了對car介面的實現
class SportsCar extends CarAdapter{
publicvoid run(){
System.out.println("my car is running");
}
publicvoid addOil(){
System.out.println("my car is adding oil");
}
}
publicclass hello{
publicstaticvoid main(String args[]){
//實現了car介面的SportCar
Car c =new SportsCar();
c.run();
c.addOil();
}
}
5、 設計模式——觀察者模式
通過觀察者模式,我們可以監控被觀察物件的變化,達到及時監督的目的。
import java.util.Observable;
import java.util.Observer;
//房屋(被觀察物件),需繼承Obserable類
class House extends Observable{
privatefloat price;
public House(float price){this.price = price;}
publicfloat getPrice(){returnthis.price;}
publicvoid setPrice(float price){
//設定觀察點
super.setChanged();
//通知觀察者
super.notifyObservers(price);
this.price = price;
}
public String toString(){
return"house's price is "+this.price;
}
}
//觀察者,需實現Observer介面,介面中只有update方法需要實現
class HouseObserver implements Observer{
private String name;
public HouseObserver(String name){this.name = name;}
//觀察者觀察到的物件,和觀察到的改變了的引數
publicvoid update(Observable obj, Object arg){
if(arg instanceofFloat){
System.out.println(this.name +" observ the price changed to : "+(float)arg);
}
}
}
publicclass hello{
publicstaticvoid main(String args[])throws Exception{
//觀察物件
House house =new House(10000);
//三個觀察者
HouseObserver ho1 =new HouseObserver("kaka");
HouseObserver ho2 =new HouseObserver("fedy");
HouseObserver ho3 =new HouseObserver("tony");
//觀察者關注觀察物件
house.addObserver(ho1);
house.addObserver(ho2);
house.addObserver(ho3);
//輸出房屋價格,修改房屋價格,輸出修改後的服務價格
//檢視觀察者是否觀察到房屋價格的變化
System.out.println(house);
house.setPrice(12888);
System.out.println(house);
}
}