一、原型模式
1、什么是原型模式
克隆
原型模式是一個(gè)創(chuàng)建型的模式。原型二字表明了改模式應(yīng)該有一個(gè)樣板實(shí)例,用戶從這個(gè)樣板對(duì)象中復(fù)制一個(gè)內(nèi)部屬性一致的對(duì)象,這個(gè)過程也就是我們稱的“克隆”。被復(fù)制的實(shí)例就是我們所稱的“原型”,這個(gè)原型是可定制的。原型模式多用于創(chuàng)建復(fù)雜的或者構(gòu)造耗時(shí)的實(shí)例,因?yàn)檫@種情況下,復(fù)制一個(gè)已經(jīng)存在的實(shí)例可使程序運(yùn)行更高效。
2、原型模式應(yīng)用場景
- (1)類初始化需要消化非常多的資源,這個(gè)資源包括數(shù)據(jù)、硬件資源等,通過原型拷貝避免這些消耗。
- (2)通過new產(chǎn)生的一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或者權(quán)限,這時(shí)可以使用原型模式。
- (3)一個(gè)對(duì)象需要提供給其他對(duì)象訪問,而且各個(gè)調(diào)用者可能都需要修改其值時(shí),可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者使用,即保護(hù)性拷貝。
Spring框架中的多例就是使用原型。
3、原型模式UML類圖(通用)
原型模式主要用于對(duì)象的復(fù)制,它的核心是就是類圖中的原型類Prototype。Prototype類需要具備以下兩個(gè)條件:
- (1)實(shí)現(xiàn)Cloneable接口。在java語言有一個(gè)Cloneable接口,它的作用只有一個(gè),就是在運(yùn)行時(shí)通知虛擬機(jī)可以安全地在實(shí)現(xiàn)了此接口的類上使用clone方法。在java虛擬機(jī)中,只有實(shí)現(xiàn)了這個(gè)接口的類才可以被拷貝,否則在運(yùn)行時(shí)會(huì)拋出CloneNotSupportedException異常。
- (2)重寫Object類中的clone方法。Java中,所有類的父類都是Object類,Object類中有一個(gè)clone方法,作用是返回對(duì)象的一個(gè)拷貝,但是其作用域protected類型的,一般的類無法調(diào)用,因此Prototype類需要將clone方法的作用域修改為public類型。
4、原型模式分類
演示實(shí)例
/*
* 書本類型,扮演的是ConcretePrototype角色,而Cloneable扮演Prototype角色
*/
public class Book implements Cloneable {
private String title;// 標(biāo)題
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();//深復(fù)制
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;
}
/**
* 打印內(nèi)容
*/
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、原型模式分為淺復(fù)制和深復(fù)制
- 淺復(fù)制 —-只是拷貝了基本類型的數(shù)據(jù),而引用類型數(shù)據(jù),復(fù)制后也是會(huì)發(fā)生引用,我們把這種拷貝叫做“(淺復(fù)制)淺拷貝”,換句話說,淺復(fù)制僅僅是指向被復(fù)制的內(nèi)存地址,如果原地址中對(duì)象被改變了,那么淺復(fù)制出來的對(duì)象也會(huì)相應(yīng)改變。
- 深復(fù)制 —-在計(jì)算機(jī)中開辟了一塊新的內(nèi)存地址用于存放復(fù)制的對(duì)象。
二、策略模式
1、什么是策略模式
定義了一系列的算法,并將每一個(gè)算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。
2、策略模式由三種角色組成
策略模式應(yīng)用場景
策略模式的用意是針對(duì)一組算法或邏輯,將每一個(gè)算法或邏輯封裝到具有共同接口的獨(dú)立的類中,從而使得它們之間可以相互替換。策略模式使得算法或邏輯可以在不影響到客戶端的情況下發(fā)生變化。說到策略模式就不得不提及OCP(Open Closed Principle) 開閉原則,即對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。策略模式的出現(xiàn)很好地詮釋了開閉原則,有效地減少了分支語句。
3、策略模式代碼
此代碼通過模擬不同會(huì)員購物車打折力度不同分為三種策略,初級(jí)會(huì)員,中級(jí)會(huì)員,高級(jí)會(huì)員。
//策略模式 定義抽象方法 所有支持公共接口
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");
}
}
// 使用上下文維護(hù)算法策略
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),是一種行為型模型,行為型模式關(guān)注的是系統(tǒng)中對(duì)象之間的相互交互,解決系統(tǒng)在運(yùn)行時(shí)對(duì)象之間的相互通信和協(xié)作,進(jìn)一步明確對(duì)象的職責(zé)。相比來說,創(chuàng)建型模式關(guān)注對(duì)象的創(chuàng)建過程,結(jié)構(gòu)型模式關(guān)注對(duì)象和類的組合關(guān)系。
2、模式的職責(zé)
觀察者模式主要用于1對(duì)N的通知。當(dāng)一個(gè)對(duì)象的狀態(tài)變化時(shí),他需要及時(shí)告知一系列對(duì)象,令他們做出相應(yīng)。
實(shí)現(xiàn)有兩種方式:
- 推:每次都會(huì)把通知以廣播的方式發(fā)送給所有觀察者,所有的觀察者只能被動(dòng)接收。
- 拉:觀察者只要知道有情況即可,至于什么時(shí)候獲取內(nèi)容,獲取什么內(nèi)容,都可以自主決定。
3、模式的實(shí)現(xiàn)
//觀察者的接口,用來存放觀察者共有方法
public interface Observer {
// 觀察者方法
void update(Subjecct subjecct);
}
//觀察對(duì)象的父類
public class Subjecct {
//觀察者的存儲(chǔ)集合
private List<Observer> list = new ArrayList<>();
// 注冊(cè)觀察者方法
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);
}
}
}
//具體觀察者對(duì)象的實(shí)現(xiàn)
public class RealObserver extends Subjecct {
//被觀察對(duì)象的屬性
private int state;
public int getState(){
return state;
}
public void setState(int state){
this.state=state;
//主題對(duì)象(目標(biāo)對(duì)象)值發(fā)生改變
this.notifyAllObserver();
}
}
public class Client {
public static void main(String[] args) {
// 目標(biāo)對(duì)象
RealObserver subject = new RealObserver();
// 創(chuàng)建多個(gè)觀察者
ObserverA obs1 = new ObserverA();
ObserverA obs2 = new ObserverA();
ObserverA obs3 = new ObserverA();
// 注冊(cè)到觀察隊(duì)列中
subject.registerObserver(obs1);
subject.registerObserver(obs2);
subject.registerObserver(obs3);
// 改變State狀態(tài)
subject.setState(300);
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
// 改變State狀態(tài)
subject.setState(400);
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
}
}
4、觀察者模式應(yīng)用場景
關(guān)聯(lián)行為場景,需要注意的是,關(guān)聯(lián)行為是可拆分的,而不是“組合”關(guān)系。
事件多級(jí)觸發(fā)場景。
跨系統(tǒng)的消息交換場景,如消息隊(duì)列、事件總線的處理機(jī)制。
個(gè)人博客 蝸牛