設計模式之原型模式、策略模式、觀察者模式
一、原型模式
1、什麼是原型模式
克隆
原型模式是一個建立型的模式。原型二字表明瞭改模式應該有一個樣板例項,使用者從這個樣板物件中複製一個內部屬性一致的物件,這個過程也就是我們稱的“克隆”。被複制的例項就是我們所稱的“原型”,這個原型是可定製的。原型模式多用於建立複雜的或者構造耗時的例項,因為這種情況下,複製一個已經存在的例項可使程式執行更高效。
2、原型模式應用場景
- (1)類初始化需要消化非常多的資源,這個資源包括資料、硬體資源等,通過原型拷貝避免這些消耗。
- (2)通過new產生的一個物件需要非常繁瑣的資料準備或者許可權,這時可以使用原型模式。
- (3)一個物件需要提供給其他物件訪問,而且各個呼叫者可能都需要修改其值時,可以考慮使用原型模式拷貝多個物件供呼叫者使用,即保護性拷貝。
Spring框架中的多例就是使用原型。
3、原型模式UML類圖(通用)
原型模式主要用於物件的複製,它的核心是就是類圖中的原型類Prototype。Prototype類需要具備以下兩個條件:
- (1)實現Cloneable介面。在java語言有一個Cloneable介面,它的作用只有一個,就是在執行時通知虛擬機器器可以安全地在實現了此介面的類上使用clone方法。在java虛擬機器器中,只有實現了這個介面的類才可以被拷貝,否則在執行時會丟擲CloneNotSupportedException異常。
- (2)重寫Object類中的clone方法。Java中,所有類的父類都是Object類,Object類中有一個clone方法,作用是返回物件的一個拷貝,但是其作用域protected型別的,一般的類無法呼叫,因此Prototype類需要將clone方法的作用域修改為public型別。
4、原型模式分類
演示例項
/*
* 書本型別,扮演的是ConcretePrototype角色,而Cloneable扮演Prototype角色
*/
public class Book implements Cloneable {
private String title;// 標題
private ArrayList<String> image = new ArrayList<String>();// 圖片名列表
public Book() {
super();
}
/**
* 重寫拷貝方法
*/
@Override
protected Book clone() {
try {
Book book = (Book) super.clone();//
book.image=(ArrayList<String>)this.image.clone();//深複製
return book;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public ArrayList<String> getImage() {
return image;
}
public void addImage(String img) {
this.image.add(img);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
/**
* 列印內容
*/
public void showBook() {
System.out.println("----------------------Start----------------------");
System.out.println("title:" + title);
for (String img : image) {
System.out.println("image name:" + img);
}
System.out.println("----------------------End----------------------");
}
}
複製程式碼
客戶端程式碼
public class Client02 {
public static void main(String[] args) {
Book book1 = new Book();
book1.setTitle("書1");
book1.addImage("圖1");
book1.showBook();
//以原型方式拷貝一份
Book book2 = book1.clone();
book2.showBook();
book2.setTitle("書2");
book2.addImage("圖2");
book2.showBook();
//再次還原列印書本
book1.showBook();
}
}複製程式碼
5、原型模式分為淺複製和深複製
- 淺複製 —-只是拷貝了基本型別的資料,而引用型別資料,複製後也是會發生引用,我們把這種拷貝叫做“(淺複製)淺拷貝”,換句話說,淺複製僅僅是指向被複制的記憶體地址,如果原地址中物件被改變了,那麼淺複製出來的物件也會相應改變。
- 深複製 —-在計算機中開闢了一塊新的記憶體地址用於存放複製的物件。
二、策略模式
1、什麼是策略模式
定義了一系列的演演算法,並將每一個演演算法封裝起來,而且使它們還可以相互替換。策略模式讓演演算法獨立於使用它的客戶而獨立變化。
2、策略模式由三種角色組成
策略模式應用場景
策略模式的用意是針對一組演演算法或邏輯,將每一個演演算法或邏輯封裝到具有共同介面的獨立的類中,從而使得它們之間可以相互替換。策略模式使得演演算法或邏輯可以在不影響到客戶端的情況下發生變化。說到策略模式就不得不提及OCP(Open Closed Principle) 開閉原則,即對擴充套件開放,對修改關閉。策略模式的出現很好地詮釋了開閉原則,有效地減少了分支語句。
3、策略模式程式碼
此程式碼通過模擬不同會員購物車打折力度不同分為三種策略,初級會員,中級會員,高階會員。
//策略模式 定義抽象方法 所有支援公共介面
abstract class Strategy {
// 演演算法方法
abstract void algorithmInterface();
}
class StrategyA extends Strategy {
@Override
void algorithmInterface() {
System.out.println("演演算法A");
}
}
class StrategyB extends Strategy {
@Override
void algorithmInterface() {
System.out.println("演演算法B");
}
}
class StrategyC extends Strategy {
@Override
void algorithmInterface() {
System.out.println("演演算法C");
}
}
// 使用上下文維護演演算法策略
class Context {
Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void algorithmInterface() {
strategy.algorithmInterface();
}
}
class ClientTestStrategy {
public static void main(String[] args) {
Context context;
context = new Context(new StrategyA());
context.algorithmInterface();
context = new Context(new StrategyB());
context.algorithmInterface();
context = new Context(new StrategyC());
context.algorithmInterface();
}
}複製程式碼
三、觀察者模式
1、什麼是觀察者模式
觀察者模式(Observer),是一種行為型模型,行為型模式關注的是系統中物件之間的相互互動,解決系統在執行時物件之間的相互通訊和協作,進一步明確物件的職責。相比來說,建立型模式關注物件的建立過程,結構型模式關注物件和類的組合關係。
2、模式的職責
觀察者模式主要用於1對N的通知。當一個物件的狀態變化時,他需要及時告知一系列物件,令他們做出相應。實現有兩種方式:
- 推:每次都會把通知以廣播的方式傳送給所有觀察者,所有的觀察者只能被動接收。
- 拉:觀察者只要知道有情況即可,至於什麼時候獲取內容,獲取什麼內容,都可以自主決定。
3、模式的實現
//觀察者的介面,用來存放觀察者共有方法
public interface Observer {
// 觀察者方法
void update(Subjecct subjecct);
}
//觀察物件的父類
public class Subjecct {
//觀察者的儲存集合
private List<Observer> list = new ArrayList<>();
// 註冊觀察者方法
public void registerObserver(Observer obs) {
list.add(obs);
}
// 刪除觀察者方法
public void removeObserver(Observer obs) {
list.remove(obs);
this.notifyAllObserver();
}
// 通知所有的觀察者更新
public void notifyAllObserver() {
for (Observer observer : list) {
observer.update(this);
}
}
}
//具體觀察者物件的實現
public class RealObserver extends Subjecct {
//被觀察物件的屬性
private int state;
public int getState(){
return state;
}
public void setState(int state){
this.state=state;
//主題物件(目標物件)值發生改變
this.notifyAllObserver();
}
}
public class Client {
public static void main(String[] args) {
// 目標物件
RealObserver subject = new RealObserver();
// 建立多個觀察者
ObserverA obs1 = new ObserverA();
ObserverA obs2 = new ObserverA();
ObserverA obs3 = new ObserverA();
// 註冊到觀察佇列中
subject.registerObserver(obs1);
subject.registerObserver(obs2);
subject.registerObserver(obs3);
// 改變State狀態
subject.setState(300);
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
// 改變State狀態
subject.setState(400);
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
}
}
複製程式碼
4、觀察者模式應用場景
關聯行為場景,需要注意的是,關聯行為是可拆分的,而不是“組合”關係。事件多級觸發場景。
跨系統的訊息交換場景,如訊息佇列、事件匯流排的處理機制。
個人部落格 蝸牛