1. 程式人生 > >3、設計模式—單例、工廠、代理、介面卡、觀察者

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

void eat(){

        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);

}

}