前言
在這篇文章中,荔枝將會(huì)梳理軟件設(shè)計(jì)模式中有關(guān)觀察者模式、組合模式和享元模式的內(nèi)容。其中組合模式和享元模式比較簡單,重點(diǎn)需要理解觀察者模式的機(jī)制以及為什么該模式實(shí)現(xiàn)了對(duì)象之間的松耦合。希望荔枝的梳理能對(duì)需要的小伙伴有幫助~~~
文章目錄
前言
一、觀察者模式Observer
二、組合模式Composite
三、享元模式Flyweight
總結(jié)
一、觀察者模式Observer
????????觀察者模式是一種行為型設(shè)計(jì)模式,它定義了一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),依賴它的所有觀察者對(duì)象都會(huì)收到通知并自動(dòng)更新。這種模式跟發(fā)布訂閱的流程類似,因此有些人又稱該模式為發(fā)布訂閱模式。觀察者模式的核心思想是解耦,觀察者模式通過將主題和觀察者解耦,實(shí)現(xiàn)了對(duì)象之間的松耦合。當(dāng)主題的狀態(tài)發(fā)生改變時(shí),所有依賴于它的觀察者都會(huì)收到通知并進(jìn)行相應(yīng)的更新。在觀察者模式中,主題只知道觀察者的存在,并不知道觀察者的具體實(shí)現(xiàn)。當(dāng)主題狀態(tài)發(fā)生改變時(shí),它只需要通知觀察者即可,而不需要關(guān)心觀察者的具體實(shí)現(xiàn)。
關(guān)于觀察者模式和發(fā)布訂閱模式的異同,也有些博主的文章進(jìn)行區(qū)分,這里可以看:
https://juejin.cn/post/6844903603107266567?searchId=202309082143393C968B11EA74CF13EAF1
觀察者模式的結(jié)構(gòu)組成如下,一般來說我們都會(huì)定義一個(gè)事件類,當(dāng)觸發(fā)了這個(gè)事件就會(huì)由觀察者調(diào)用對(duì)應(yīng)的事件執(zhí)行方法。
????????在下面的demo中,我們定義了事件類、觀察者接口及其對(duì)應(yīng)的實(shí)現(xiàn)類。當(dāng)我們實(shí)例化觀察者對(duì)象之后就會(huì)調(diào)用addActionListener方法并將傳入對(duì)應(yīng)的觀察者實(shí)例對(duì)象作為參數(shù)。這個(gè)時(shí)候所有的觀察者對(duì)象就會(huì)被加入到對(duì)應(yīng)的觀察者列表中并等待對(duì)應(yīng)事件觸發(fā),這里是一個(gè)按鍵的操作buttonPressed()。當(dāng)事件觸發(fā)后觀察者對(duì)象就會(huì)被觀察者列表中一 一獲取出來并調(diào)用對(duì)應(yīng)的actionPerformed方法。
package com.crj.observer;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Button b = new Button();
b.addActionListener(new MyActionListener1());
b.addActionListener(new MyActionListener2());
b.buttonPressed();
}
}
/**
* 觀察者觀察的對(duì)象
*/
class Button {
private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
public void buttonPressed() {
ActionEvent e = new ActionEvent(System.currentTimeMillis(),this);
for(int i=0; i<actionListeners.size(); i++) {
ActionListener l = actionListeners.get(i);
l.actionPerformed(e);
}
}
public void addActionListener(ActionListener l) {
actionListeners.add(l);
}
}
//觀察者
interface ActionListener {
public void actionPerformed(ActionEvent e);
}
class MyActionListener1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("button pressed!");
}
}
class MyActionListener2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("button pressed 2!");
}
}
/**
* 事件類
*/
class ActionEvent {
long when;
Object source;
public ActionEvent(long when, Object source) {
super();
this.when = when;
this.source = source;
}
public long getWhen() {
return when;
}
//事件源對(duì)象
public Object getSource() {
return source;
}
}
????????這里可能會(huì)有疑問,為什么這就是觀察者模式了?在前面我們提及觀察者模式其實(shí)是一種松耦合的機(jī)制,它降低了對(duì)象之間的耦合度,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),依賴它的所有觀察者對(duì)象都會(huì)收到通知并自動(dòng)更新。在這段demo中我們借助一個(gè)事件類定義獲取事件源對(duì)象的方法,同時(shí)將不同觀察者對(duì)象的實(shí)例放入了一個(gè)list列表,此時(shí)觀察者們會(huì)等待事件觸發(fā)并獲得它們所依賴的(觀察 | 監(jiān)聽)對(duì)象的變化信息(這里指的是方法的觸發(fā)),這其實(shí)就是觀察者模式的機(jī)制。
二、組合模式Composite
????????組合模式(Composite Pattern),又叫部分整體模式,是用于把一組相似的對(duì)象當(dāng)作一個(gè)單一的對(duì)象。組合模式依據(jù)樹形結(jié)構(gòu)來組合對(duì)象,用來表示部分以及整體層次,它創(chuàng)建了對(duì)象組的樹形結(jié)構(gòu),也提供了修改相同對(duì)象組的方式??梢哉f,組合模式是樹狀結(jié)構(gòu)的專用模式。
其實(shí)跟樹形數(shù)據(jù)結(jié)構(gòu)類似,區(qū)分根節(jié)點(diǎn)和葉節(jié)點(diǎn),將LeafNode和BranchNode通過tree的方式組合在一起,根節(jié)點(diǎn)下的子節(jié)點(diǎn)可以是一個(gè)根節(jié)點(diǎn)。
package com.crj.composite;
import java.util.ArrayList;
import java.util.List;
abstract class Node {
abstract public void p();
}
class LeafNode extends Node {
String content;
public LeafNode(String content) {this.content = content;}
@Override
public void p() {
System.out.println(content);
}
}
class BranchNode extends Node {
List<Node> nodes = new ArrayList<>();
String name;
public BranchNode(String name) {this.name = name;}
@Override
public void p() {
System.out.println(name);
}
public void add(Node n) {
nodes.add(n);
}
}
public class Main {
public static void main(String[] args) {
BranchNode root = new BranchNode("root");
BranchNode chapter1 = new BranchNode("chapter1");
BranchNode chapter2 = new BranchNode("chapter2");
Node r1 = new LeafNode("r1");
Node c11 = new LeafNode("c11");
Node c12 = new LeafNode("c12");
BranchNode b21 = new BranchNode("section21");
Node c211 = new LeafNode("c211");
Node c212 = new LeafNode("c212");
root.add(chapter1);
root.add(chapter2);
root.add(r1);
chapter1.add(c11);
chapter1.add(c12);
chapter2.add(b21);
b21.add(c211);
b21.add(c212);
tree(root, 0);
}
static void tree(Node b, int depth) {
for(int i=0; i<depth; i++) System.out.print("--");
b.p();
if(b instanceof BranchNode) {
for (Node n : ((BranchNode)b).nodes) {
tree(n, depth + 1);
}
}
}
}
三、享元模式Flyweight
????????享元模式(Flyweight Pattern)主要用于減少創(chuàng)建對(duì)象的數(shù)量,以減少內(nèi)存占用和提高性能。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它提供了減少對(duì)象數(shù)量從而改善應(yīng)用所需的對(duì)象結(jié)構(gòu)的方式。享元模式嘗試重用現(xiàn)有的同類對(duì)象,如果未找到匹配的對(duì)象,則創(chuàng)建新對(duì)象。???????享元模式在Java里面的一個(gè)比較常見的應(yīng)用就是對(duì)字符和字符串的存儲(chǔ)。
package com.crj.flyweight;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
class Bullet{
public UUID id = UUID.randomUUID();
boolean living = true;
@Override
public String toString() {
return "Bullet{" +
"id=" + id +
'}';
}
}
public class BulletPool {
List<Bullet> bullets = new ArrayList<>();
{
for(int i=0; i<5; i++) bullets.add(new Bullet());
}
public Bullet getBullet() {
for(int i=0; i<bullets.size(); i++) {
Bullet b = bullets.get(i);
if(!b.living) return b;
}
return new Bullet();
}
public static void main(String[] args) {
BulletPool bp = new BulletPool();
for(int i=0; i<10; i++) {
Bullet b = bp.getBullet();
System.out.println(b);
}
}
}
享元模式相當(dāng)于將創(chuàng)建的對(duì)象放進(jìn)一個(gè)類似對(duì)象池的東西,需要的時(shí)候就會(huì)將對(duì)象激活并給出去,只有在不夠的時(shí)候才會(huì)重新new一個(gè)對(duì)象。這其實(shí)也是一種池化的思想。
總結(jié)
????????到現(xiàn)在荔枝已經(jīng)學(xué)習(xí)了十種軟件設(shè)計(jì)模式了,這些設(shè)計(jì)模式確實(shí)會(huì)在代碼結(jié)構(gòu)層面帶來較好的優(yōu)化,使得可拓展性更好,同時(shí)設(shè)計(jì)模式之間也是存在關(guān)聯(lián)的,我們正常在使用的時(shí)候也可能會(huì)同時(shí)使用一種或多種設(shè)計(jì)模式。而對(duì)于設(shè)計(jì)模式的選擇,則應(yīng)該是適合業(yè)務(wù)的才是最好的哈哈哈哈。文章來源:http://www.zghlxwxcb.cn/news/detail-703892.html
今朝已然成為過去,明日依然向往未來!我是小荔枝,在技術(shù)成長的路上與你相伴,碼文不易,麻煩舉起小爪爪點(diǎn)個(gè)贊吧哈哈哈~~~?比心心?~~~文章來源地址http://www.zghlxwxcb.cn/news/detail-703892.html
到了這里,關(guān)于軟件設(shè)計(jì)模式(四):觀察者、組合、享元模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!