設計模式說明
設計模式(Design Patterns)是在軟件設計中經常使用的最佳實踐的描述妹笆,它們是經過多年的實踐和驗證的。下面是一些常見的設計模式:
創(chuàng)建型模式(Creational Patterns)
- 單例模式(Singleton)
保證一個類只有一個實例停局。
- 工廠模式(Factory)
將對象的創(chuàng)建過程交給子類去實現(xiàn)叉跛。
- 抽象工廠模式(Abstract Factory)
提供一個接口用于創(chuàng)建一系列相關的對象功咒。
- 建造者模式(Builder)
分步創(chuàng)建復雜對象。
- 原型模式(Prototype)
通過克隆創(chuàng)建新對象绷跑。
結構型模式(Structural Patterns)
- 適配器模式(Adapter)
將不兼容的接口轉換成兼容的接口。
- 橋接模式(Bridge)
將抽象部分和具體實現(xiàn)部分分離凡资。
- 組合模式(Composite)
統(tǒng)一處理單個對象和組合對象砸捏。
- 裝飾器模式(Decorator)
動態(tài)地給對象添加新的功能。
- 外觀模式(Facade)
簡化復雜系統(tǒng)的接口隙赁。
- 享元模式(Flyweight)
共享細粒度的對象垦藏,以節(jié)省內存。
- 代理模式(Proxy)
通過代理控制對象的訪問伞访。
行為型模式(Behavioral Patterns)
- 職責鏈模式(Chain of Responsibility)
請求沿處理鏈傳遞掂骏,避免耦合。
- 命令模式(Command)
封裝請求對象厚掷,解耦發(fā)送和接收弟灼。
- 解釋器模式(Interpreter)
解釋執(zhí)行語言語句。
- 迭代器模式(Iterator)
遍歷集合元素蝗肪。
- 中介者模式(Mediator)
解耦多個對象之間的交互關系袜爪。
- 備忘錄模式(Memento)
保存對象狀態(tài)。
- 觀察者模式(Observer)
當對象狀態(tài)發(fā)生變化時薛闪,通知它的依賴者辛馆。
- 狀態(tài)模式(State)
根據(jù)對象的狀態(tài),改變對象的行為豁延。
- 策略模式(Strategy)
定義一系列算法昙篙,封裝每個算法,并使它們可以互換诱咏。
- 模板方法模式(Template Method)
定義一個算法的骨架苔可,具體實現(xiàn)由子類完成。
- 訪問者模式(Visitor)
封裝對數(shù)據(jù)結構的操作袋狞。
以上是常見的設計模式焚辅,每個模式都有自己的特點和應用場景映屋。在軟件設計中,根據(jù)需要選擇適當?shù)脑O計模式可以提高代碼的質量同蜻、可維護性和可擴展性棚点。
模式詳解
單例模式(Singleton)
保證一個類只有一個實例。
// 它確保一個類只能被實例化一次湾蔓,從而保證系統(tǒng)中只存在一個該類的實例瘫析。
object Singleton {
init {
// 在這里初始化單例對象
}
fun doSomething() {
// 這里是單例對象的方法
}
}
- 提供一個全局唯一的訪問點:使用單例模式可以確保系統(tǒng)中只存在一個實例對象,從而提供一個全局唯一的訪問點默责,使得其他對象能夠方便地訪問該實例贬循。
- 控制對象的生成:由于單例模式只能生成一個實例對象,因此可以對實例對象的生成過程進行嚴格控制桃序,確保系統(tǒng)中只有一個實例對象杖虾,并且該對象在系統(tǒng)中始終存在。
- 節(jié)省系統(tǒng)資源:由于單例模式只生成一個實例對象葡缰,因此可以節(jié)省系統(tǒng)資源亏掀,避免創(chuàng)建過多的對象導致系統(tǒng)負擔過重。
- 實現(xiàn)數(shù)據(jù)共享:單例模式可以實現(xiàn)數(shù)據(jù)共享泛释,即多個對象共享同一個實例對象的數(shù)據(jù)础米,從而避免了數(shù)據(jù)不一致的問題怎栽。
- 簡化系統(tǒng)調用:由于單例模式提供了一個全局唯一的訪問點,因此可以簡化系統(tǒng)調用,避免了頻繁地創(chuàng)建和銷毀對象所帶來的系統(tǒng)開銷觅捆。
工廠方法模式(Factory Method Pattern)
將對象的創(chuàng)建過程交給子類去實現(xiàn)粮坞。
interface Exporter {
fun export(data: String): String
}
class PDFExporter : Exporter {
override fun export(data: String): String {
return "Exporting data to PDF format: $data"
}
}
class CSVExporter : Exporter {
override fun export(data: String): String {
return "Exporting data to CSV format: $data"
}
}
interface ExporterFactory {
fun createExporter(): Exporter
}
class PDFExporterFactory : ExporterFactory {
override fun createExporter(): Exporter {
return PDFExporter()
}
}
class CSVExporterFactory : ExporterFactory {
override fun createExporter(): Exporter {
return CSVExporter()
}
}
- 封裝對象的創(chuàng)建:將對象的創(chuàng)建封裝在工廠類中鹰祸,使得客戶端無需關注具體對象的創(chuàng)建過程碉输。
- 實現(xiàn)對象的多態(tài)性:通過定義抽象工廠和具體工廠,實現(xiàn)了對象的多態(tài)性裙顽,客戶端可以通過工廠接口來獲取不同的具體對象付燥。
- 對象創(chuàng)建和使用分離:工廠方法模式將對象的創(chuàng)建和使用分離開來,降低了客戶端代碼的復雜性愈犹,客戶端只需要關注如何使用對4. 象键科,而無需了解對象的創(chuàng)建過程。
- 靈活性和可維護性:工廠方法模式可以通過增加或修改具體工廠來創(chuàng)建不同的對象漩怎,而不需要修改客戶端代碼勋颖,增加了系統(tǒng)的靈6. 活性和可維護性。
- 開閉原則:工廠方法模式可以通過增加新的具體工廠來創(chuàng)建新的對象勋锤,而不需要修改已有的代碼饭玲,實現(xiàn)了對擴展開放,對修改關閉的開閉原則叁执。
- 單一職責原則:將對象的創(chuàng)建職責分離出去茄厘,讓每個類都只負責一件事情矮冬,遵循了單一職責原則。
抽象工廠模式(Abstract Factory)
提供一個接口用于創(chuàng)建一系列相關的對象蚕断。
// 定義抽象工廠接口
interface AbstractFactory {
fun createProduct(): Product
}
// 定義具體工廠1欢伏,實現(xiàn)抽象工廠接口
class ConcreteFactory1 : AbstractFactory {
override fun createProduct(): Product {
return ConcreteProduct1()
}
}
// 定義具體工廠2入挣,實現(xiàn)抽象工廠接口
class ConcreteFactory2 : AbstractFactory {
override fun createProduct(): Product {
return ConcreteProduct2()
}
}
// 定義抽象產品接口
interface Product {
fun operation()
}
// 定義具體產品1亿乳,實現(xiàn)抽象產品接口
class ConcreteProduct1 : Product {
override fun operation() {
println("Product 1 operation")
}
}
// 定義具體產品2,實現(xiàn)抽象產品接口
class ConcreteProduct2 : Product {
override fun operation() {
println("Product 2 operation")
}
}
// 客戶端代碼
fun main() {
val factory1 = ConcreteFactory1()
val product1 = factory1.createProduct()
product1.operation()
val factory2 = ConcreteFactory2()
val product2 = factory2.createProduct()
product2.operation()
}
- 封裝一組相互關聯(lián)的產品對象創(chuàng)建:抽象工廠模式能夠將一組相互關聯(lián)的產品對象的創(chuàng)建封裝在一起径筏,使得客戶端可以通過接口訪問它們葛假,而不必知道它們的具體實現(xiàn)細節(jié)。這樣就能夠將產品對象的創(chuàng)建和客戶端代碼分離開來滋恬,降低了客戶端代碼的復雜度聊训,提高了代碼的可維護性。
- 便于替換產品族:抽象工廠模式能夠讓客戶端使用不同的具體工廠來創(chuàng)建不同的產品族恢氯,從而實現(xiàn)對產品族的替換带斑。這樣就能夠靈活地改變系統(tǒng)中的產品組合,滿足不同的需求勋拟。
- 保證產品對象的一致性:抽象工廠模式能夠保證一個工廠創(chuàng)建的所有產品對象都屬于同一產品族勋磕,這樣就能夠保證這些產品對象之間的一致性,從而避免了不同產品之間的兼容性問題敢靡。
- 增加新的產品族方便:抽象工廠模式能夠方便地增加新的產品族挂滓,只需要增加新的具體工廠和新的具體產品即可。這樣就能夠讓系統(tǒng)具有良好的擴展性和可維護性啸胧。
- 不容易增加新的產品等級結構:抽象工廠模式對于增加新的產品等級結構比較困難赶站,因為需要修改所有的具體工廠類。如果需要增加新的產品等級結構纺念,最好的方式是采用工廠方法模式或者簡單工廠模式贝椿。
建造者模式(Builder)
分步創(chuàng)建復雜對象。
class Person(
val name: String,
val age: Int,
val gender: String,
val height: Int,
val weight: Int
) {
override fun toString(): String {
return "Name: $name, Age: $age, Gender: $gender, Height: $height cm, Weight: $weight kg"
}
}
class PersonBuilder(
var name: String = "",
var age: Int = 0,
var gender: String = "",
var height: Int = 0,
var weight: Int = 0
) {
fun setName(name: String): PersonBuilder {
this.name = name
return this
}
fun setAge(age: Int): PersonBuilder {
this.age = age
return this
}
fun setGender(gender: String): PersonBuilder {
this.gender = gender
return this
}
fun setHeight(height: Int): PersonBuilder {
this.height = height
return this
}
fun setWeight(weight: Int): PersonBuilder {
this.weight = weight
return this
}
fun build(): Person {
return Person(name, age, gender, height, weight)
}
}
- 分離構建過程:將一個復雜對象的構建過程分解為多個簡單的構建步驟陷谱,使得不同的構建者可以重用相同的構建過程來構建不同的對象實例烙博。
- 封裝構建細節(jié):將構建過程中的細節(jié)封裝在一個獨立的建造者對象中,使得客戶端代碼無需了解對象的構建過程叭首,從而提高了代碼的可維護性和可擴展性习勤。
- 實現(xiàn)構建復雜對象:通過組合不同的構建步驟,建造者模式可以實現(xiàn)構建復雜對象焙格,而不需要暴露對象的內部結構和細節(jié)图毕。
- 支持不同的表示方式:建造者模式可以通過不同的構建者對象來實現(xiàn)不同的表示方式,例如不同的組裝方式眷唉、不同的配置選項等予颤。
- 靈活性和可擴展性:由于建造者模式將構建過程封裝在一個獨立的對象中囤官,因此可以很容易地添加新的構建者對象來支持新的對象表示方式,從而提高了系統(tǒng)的靈活性和可擴展性蛤虐。
原型模式(Prototype)
通過克隆創(chuàng)建新對象党饮。
data class SimplePrototype(var value: Int) : Cloneable {
public override fun clone(): SimplePrototype {
return super.clone() as SimplePrototype
}
}
fun main() {
// 創(chuàng)建原型對象
val prototype = SimplePrototype(10)
// 克隆原型對象
val clone = prototype.clone()
// 打印克隆對象的值
println(clone.value) // 輸出:10
}
- 克隆對象:通過克隆現(xiàn)有對象來創(chuàng)建新的對象實例,避免了重新創(chuàng)建對象所需的初始化過程驳庭,提高了性能刑顺。
- 簡化對象創(chuàng)建:原型模式使得對象創(chuàng)建變得簡單,只需復制現(xiàn)有對象即可饲常,無需了解其內部實現(xiàn)蹲堂。
- 支持動態(tài)配置對象:通過克隆現(xiàn)有對象并修改其屬性,可以方便地配置新的對象贝淤。
- 避免對原型對象的修改:由于克隆的對象是一個新的對象實例柒竞,因此可以避免對原型對象進行修改而影響到其他對象。
- 隱藏對象創(chuàng)建細節(jié):原型模式將對象創(chuàng)建過程封裝在原型對象內部播聪,隱藏了對象創(chuàng)建的細節(jié)朽基,使得客戶端代碼更加簡潔。
需要注意的是离陶,在使用原型模式時稼虎,被克隆的對象必須實現(xiàn) Cloneable 接口,并且重寫 clone() 方法枕磁。此外渡蜻,由于克隆出的對象是一個新的對象實例,因此需要注意處理對象引用的問題计济,避免出現(xiàn)對象狀態(tài)不一致的情況茸苇。
適配器模式(Adapter)
將不兼容的接口轉換成兼容的接口。
interface Target {
fun request(): String
}
class Adaptee {
fun specificRequest(): String {
return "Adaptee specific request"
}
}
class Adapter(private val adaptee: Adaptee) : Target {
override fun request(): String {
return adaptee.specificRequest()
}
}
fun main() {
// 創(chuàng)建 Adaptee 對象
val adaptee = Adaptee()
// 創(chuàng)建 Adapter 對象沦寂,并將 Adaptee 對象傳遞給它
val adapter = Adapter(adaptee)
// 調用 Target 的 request() 方法学密,實際上會調用 Adaptee 的 specificRequest() 方法
val result = adapter.request()
// 輸出結果
println(result) // 輸出:Adaptee specific request
}
- 連接不兼容的接口:適配器模式主要用于連接兩個不兼容的接口,使它們能夠協(xié)同工作传藏。適配器作為一個中間層腻暮,通過轉換一種接口調用到另一種接口的方式,使得兩種不同的接口可以在一起協(xié)同工作毯侦。
- 提供不同的接口封裝:適配器模式可以對現(xiàn)有的接口進行封裝哭靖,提供不同的接口給客戶端使用。這種封裝可以屏蔽掉底層系統(tǒng)的實現(xiàn)細節(jié)侈离,提供簡潔易用的接口給客戶端使用试幽。
- 改變接口行為:適配器模式可以改變接口的行為,使得原本不能直接使用的接口變得可以直接使用卦碾。例如铺坞,適配器可以通過對參數(shù)的轉換起宽,改變接口的行為,使得客戶端可以直接使用該接口济榨。
- 對現(xiàn)有系統(tǒng)進行重構和擴展:適配器模式可以對現(xiàn)有的系統(tǒng)進行重構和擴展坯沪。例如,當一個新的系統(tǒng)需要與現(xiàn)有系統(tǒng)進行協(xié)作時腐晾,可以通過適配器模式將其接口轉換為現(xiàn)有系統(tǒng)接口橘忱,從而實現(xiàn)協(xié)作。此外钝诚,當現(xiàn)有系統(tǒng)的接口需要修改時榄棵,可以通過適配器模式進行擴展,而不需要修改現(xiàn)有系統(tǒng)的代碼疹鳄。
橋接模式(Bridge)
將抽象部分和具體實現(xiàn)部分分離拧略。
// 實現(xiàn)化角色
interface Implementor {
fun operationImpl()
}
// 具體實現(xiàn)化角色
class ConcreteImplementorA : Implementor {
override fun operationImpl() {
println("具體實現(xiàn)A的方法執(zhí)行")
}
}
class ConcreteImplementorB : Implementor {
override fun operationImpl() {
println("具體實現(xiàn)B的方法執(zhí)行")
}
}
// 抽象化角色
abstract class Abstraction(private val implementor: Implementor) {
abstract fun operation()
fun getImplementor(): Implementor {
return implementor
}
}
// 擴展抽象化角色
class RefinedAbstraction(implementor: Implementor) : Abstraction(implementor) {
override fun operation() {
println("擴展抽象化RefinedAbstraction調用:")
getImplementor().operationImpl()
}
}
// 客戶端
fun main() {
val implementorA = ConcreteImplementorA()
val abstraction = RefinedAbstraction(implementorA)
abstraction.operation()
val implementorB = ConcreteImplementorB()
val abstractionB = RefinedAbstraction(implementorB)
abstractionB.operation()
}
- 分離抽象與實現(xiàn):橋接模式通過將抽象化和實現(xiàn)化分離垫蛆,使它們可以獨立變化腺怯,而不相互影響呛占。這樣可以使抽象化角色和實現(xiàn)化角色可以分別進行修改和擴展晾虑,而不需要修改彼此的代碼。
- 提高可擴展性:橋接模式可以通過增加實現(xiàn)化角色或抽象化角色來擴展系統(tǒng)糙捺。例如洪灯,可以通過添加一個新的實現(xiàn)化角色來增加系統(tǒng)的功能婴渡,而不需要修改現(xiàn)有的代碼边臼。
- 對系統(tǒng)進行解耦:橋接模式可以將抽象化角色和實現(xiàn)化角色分離,從而將系統(tǒng)的各個部分進行解耦柠并。這樣可以使得系統(tǒng)的不同部分可以獨立變化臼予,而不會相互影響粘拾。
- 實現(xiàn)細節(jié)對客戶端不透明:橋接模式可以將實現(xiàn)化角色的細節(jié)對客戶端進行屏蔽缰雇,使得客戶端只需要關心抽象化角色的接口械哟,而不需要關心實現(xiàn)化角色的具體實現(xiàn)暇咆。這樣可以使得客戶端代碼更加簡潔清晰爸业。
組合模式(Composite)
統(tǒng)一處理單個對象和組合對象。
// 組合模式中的抽象構件
interface Component {
fun operation()
}
// 葉子構件
class Leaf(private val name: String) : Component {
override fun operation() {
println("Leaf $name:被訪問年栓!")
}
}
// 容器構件
class Composite(private val name: String) : Component {
private val children = mutableListOf<Component>()
override fun operation() {
println("Composite $name:被訪問某抓!")
for (child in children) {
child.operation()
}
}
fun add(component: Component) {
children.add(component)
}
fun remove(component: Component) {
children.remove(component)
}
fun getChild(index: Int): Component {
return children[index]
}
}
// 客戶端
fun main() {
val root = Composite("root")
val leaf1 = Leaf("leaf1")
val leaf2 = Leaf("leaf2")
val composite1 = Composite("composite1")
val leaf3 = Leaf("leaf3")
val leaf4 = Leaf("leaf4")
val composite2 = Composite("composite2")
val leaf5 = Leaf("leaf5")
root.add(leaf1)
root.add(leaf2)
composite1.add(leaf3)
composite1.add(leaf4)
composite2.add(leaf5)
root.add(composite1)
root.add(composite2)
root.operation()
}
- 將對象組合成樹形結構:組合模式可以將一組對象組合成樹形結構,以表示"整體-部分"的層次結構备禀。這樣可以方便地處理對象之間的關系曲尸,并能夠快速地定位到需要的對象。
- 統(tǒng)一對待單個對象和組合對象:組合模式中纽乱,單個對象和組合對象被統(tǒng)一對待鸦列。這意味著客戶端代碼可以像處理單個對象一樣處理組合對象薯嗤,而不需要關心它們的具體實現(xiàn)細節(jié)骆姐。
- 簡化客戶端代碼:組合模式可以讓客戶端代碼更加簡潔和清晰诲锹。客戶端只需要與抽象的組件類打交道黄虱,而不需要關心組件的具體實現(xiàn)捻浦。這樣可以降低代碼的耦合度朱灿,提高代碼的可維護性盗扒。
- 實現(xiàn)了遞歸組合:組合模式支持遞歸組合侣灶。也就是說褥影,組合對象可以包含其他組合對象,從而形成一個復雜的樹形結構赊抖。這樣可以處理復雜的層次關系氛雪,使得系統(tǒng)更加靈活和可擴展注暗。
裝飾器模式(Decorator)
動態(tài)地給對象添加新的功能捆昏。
// 抽象組件
interface Component {
fun operation()
}
// 具體組件
class ConcreteComponent : Component {
override fun operation() {
println("執(zhí)行具體組件的操作")
}
}
// 抽象裝飾器
abstract class Decorator(private val component: Component) : Component {
override fun operation() {
component.operation()
}
}
// 具體裝飾器A
class ConcreteDecoratorA(component: Component) : Decorator(component) {
private val addedState = "New State"
override fun operation() {
super.operation()
println("具體裝飾器A的操作")
addedBehavior()
}
private fun addedBehavior() {
println("ConcreteDecoratorA增加的行為$addedState")
}
}
// 具體裝飾器B
class ConcreteDecoratorB(component: Component) : Decorator(component) {
override fun operation() {
super.operation()
addedBehavior()
}
private fun addedBehavior() {
println("具體裝飾器B的操作")
}
}
// 客戶端
fun main() {
val component = ConcreteComponent()
val decoratorA = ConcreteDecoratorA(component)
val decoratorB = ConcreteDecoratorB(decoratorA)
decoratorB.operation()
}
- 擴展原有對象的功能:裝飾器模式允許在不改變原有對象的情況下骗卜,動態(tài)地為其添加新的行為或功能寇仓。
- 靈活性和可組合性:裝飾器模式中的各個組件都可以靈活組合遍烦,且可以隨時添加或刪除裝飾器服猪,從而實現(xiàn)各種不同的組合方式和功能罢猪。
- 保持接口一致性:裝飾器模式通過繼承共同的接口膳帕,使得裝飾器與原有對象具有相同的接口危彩,從而保持了對象之間的兼容性和一致性恬砂。
外觀模式(Facade)
簡化復雜系統(tǒng)的接口蓬痒。
// 外觀類
class CarFacade {
private val engine = Engine()
private val gearbox = Gearbox()
private val brakes = Brakes()
fun start() {
engine.start()
gearbox.shiftGear(1)
brakes.release()
}
fun stop() {
gearbox.shiftGear(0)
brakes.apply()
engine.stop()
}
}
// 子系統(tǒng)類
class Engine {
fun start() {
println("Engine started.")
}
fun stop() {
println("Engine stopped.")
}
}
class Gearbox {
fun shiftGear(gear: Int) {
println("Gear shifted to $gear.")
}
}
class Brakes {
fun apply() {
println("Brakes applied.")
}
fun release() {
println("Brakes released.")
}
}
// 客戶端代碼
fun main() {
val car = CarFacade()
car.start()
car.stop()
}
- 封裝復雜的子系統(tǒng):外觀模式可以將一個或多個復雜的子系統(tǒng)進行封裝狱掂,使得客戶端不需要了解子系統(tǒng)的內部實現(xiàn)趋惨,從而降低了客戶端的復雜度器虾。
- 提供簡單的接口:外觀模式提供了一個簡單的接口兆沙,使得客戶端可以更加方便地訪問子系統(tǒng)葛圃,而不需要了解復雜的實現(xiàn)細節(jié)库正。
- 實現(xiàn)松散耦合:外觀模式可以將客戶端與子系統(tǒng)之間的依賴關系解耦褥符,從而使得系統(tǒng)更加靈活和易于維護喷楣。
享元模式(Flyweight)
共享細粒度的對象抡蛙,以節(jié)省內存粗截。
interface Flyweight {
fun operation(state: String)
}
class ConcreteFlyweight : Flyweight {
override fun operation(state: String) {
println("ConcreteFlyweight: $state")
}
}
class FlyweightFactory {
private val flyweights = mutableMapOf<String, Flyweight>()
fun getFlyweight(key: String): Flyweight {
if (!flyweights.containsKey(key)) {
flyweights[key] = ConcreteFlyweight()
}
return flyweights[key]!!
}
}
- 共享對象:通過共享對象來減少系統(tǒng)中對象的數(shù)量熊昌,從而降低系統(tǒng)的內存占用和對象的創(chuàng)建時間婿屹。
- 工廠類維護:通過工廠類來維護共享的享元對象昂利,并在需要時進行創(chuàng)建和獲取蜂奸。
- 對象復用:通過共享對象來實現(xiàn)對象的復用扩所,避免了創(chuàng)建大量的對象祖屏,從而提高系統(tǒng)的性能和效率袁勺。
- 分離內部狀態(tài)和外部狀態(tài):通過將對象的內部狀態(tài)和外部狀態(tài)分離魁兼,實現(xiàn)共享對象時只需共享內部狀態(tài)咐汞,而外部狀態(tài)可以根據(jù)具體的業(yè)務場景進行傳遞化撕。
代理模式(Proxy)
通過代理控制對象的訪問植阴。
interface Subject {
fun request()
}
class RealSubject : Subject {
override fun request() {
println("RealSubject: Handling request.")
}
}
class Proxy(private val realSubject: RealSubject) : Subject {
override fun request() {
if (checkAccess()) {
realSubject.request()
logAccess()
}
}
private fun checkAccess(): Boolean {
println("Proxy: Checking access prior to firing a real request.")
return true
}
private fun logAccess() {
println("Proxy: Logging the time of request.")
}
}
fun main() {
val realSubject = RealSubject()
val proxy = Proxy(realSubject)
proxy.request()
}
- 控制對對象的訪問:通過代理對象來控制對另一個對象的訪問憾朴,從而達到控制對象的目的众雷。
- 保護對象:通過代理對象來保護另一個對象砾省,避免非法訪問或惡意修改對象编兄。
- 實現(xiàn)遠程訪問:通過代理對象來實現(xiàn)對象的遠程訪問狠鸳,可以在不同的進程或機器之間進行通信碰煌,從而實現(xiàn)分布式系統(tǒng)芦圾。
- 實現(xiàn)延遲初始化:通過代理對象來實現(xiàn)對象的延遲初始化个少,可以根據(jù)需要來動態(tài)創(chuàng)建對象夜焦。
- 實現(xiàn)對象緩存:通過代理對象來實現(xiàn)對象的緩存茫经,可以避免重復創(chuàng)建對象卸伞,提高系統(tǒng)的性能和效率荤傲。
職責鏈模式(Chain of Responsibility)
請求沿處理鏈傳遞遂黍,避免耦合雾家。
interface Handler {
fun handleRequest(request: String): String?
fun setNextHandler(nextHandler: Handler)
}
class ConcreteHandlerA : Handler {
private var nextHandler: Handler? = null
override fun handleRequest(request: String): String? {
if (request == "A") {
return "ConcreteHandlerA handled the request"
} else {
return nextHandler?.handleRequest(request)
}
}
override fun setNextHandler(nextHandler: Handler) {
this.nextHandler = nextHandler
}
}
class ConcreteHandlerB : Handler {
private var nextHandler: Handler? = null
override fun handleRequest(request: String): String? {
if (request == "B") {
return "ConcreteHandlerB handled the request"
} else {
return nextHandler?.handleRequest(request)
}
}
override fun setNextHandler(nextHandler: Handler) {
this.nextHandler = nextHandler
}
}
fun main() {
val handlerA = ConcreteHandlerA()
val handlerB = ConcreteHandlerB()
handlerA.setNextHandler(handlerB)
println(handlerA.handleRequest("A"))
println(handlerA.handleRequest("B"))
println(handlerA.handleRequest("C"))
}
- 將請求的發(fā)送者和接收者解耦:職責鏈模式通過將請求的發(fā)送者和接收者解耦豌研,避免了它們之間的直接依賴關系鬼佣,從而提高了系統(tǒng)的靈活性和可擴展性晶衷。
- 將多個處理對象組成一條處理鏈:職責鏈模式將多個處理對象組成一條處理鏈,每個處理對象都有機會處理請求永丝,如果自己無法處理請求慕嚷,則將請求傳遞給下一個處理對象喝检。
- 沿著鏈傳遞請求:職責鏈模式沿著鏈傳遞請求挠说,直到有一個處理對象能夠處理請求為止损俭。處理對象的順序可以根據(jù)實際情況進行動態(tài)配置杆兵,從而提高了系統(tǒng)的靈活性和可配置性。
- 動態(tài)增加或修改處理鏈:職責鏈模式允許動態(tài)增加或修改處理鏈骆膝,從而可以在運行時根據(jù)實際需要進行靈活的調整阅签。
命令模式(Command)
封裝請求對象政钟,解耦發(fā)送和接收养交。
// 接收者類
class Receiver {
fun action() {
println("Receiver: executing an action.")
}
}
// 命令接口
interface Command {
fun execute()
}
// 具體命令類
class ConcreteCommand(private val receiver: Receiver) : Command {
override fun execute() {
receiver.action()
}
}
// 發(fā)起者類
class Invoker(private val command: Command) {
fun executeCommand() {
command.execute()
}
}
// 測試代碼
fun main() {
val receiver = Receiver()
val command = ConcreteCommand(receiver)
val invoker = Invoker(command)
invoker.executeCommand()
}
- 將命令的發(fā)起者和執(zhí)行者解耦:命令模式通過將命令的發(fā)起者和執(zhí)行者解耦,使得它們不需要知道彼此的存在鱼辙,從而提高了系統(tǒng)的靈活性和可擴展性倒戏。
- 將命令封裝為對象:命令模式將命令封裝為一個對象杜跷,使得可以將命令作為參數(shù)進行傳遞捂寿、保存和執(zhí)行秦陋。
- 支持撤銷操作:命令模式支持撤銷操作驳概,可以在執(zhí)行命令前保存命令的狀態(tài)顺又,以便后續(xù)進行撤銷操作。
- 支持宏命令:命令模式支持將多個命令組合成一個宏命令果录,從而可以一次執(zhí)行多個命令弱恒。
- 可以在運行時動態(tài)添加或修改命令:命令模式可以在運行時動態(tài)添加或修改命令返弹,從而可以根據(jù)實際需要進行靈活的調整义起。
解釋器模式(Interpreter)
解釋執(zhí)行語言語句。
interface Expression {
fun interpret(): Int
}
class Number(private val n: Int) : Expression {
override fun interpret(): Int {
return n
}
}
class Add(private val left: Expression, private val right: Expression) : Expression {
override fun interpret(): Int {
return left.interpret() + right.interpret()
}
}
class Subtract(private val left: Expression, private val right: Expression) : Expression {
override fun interpret(): Int {
return left.interpret() - right.interpret()
}
}
- 定義語言的語法:將文法規(guī)則表示為一個類層次結構穷蛹,由接口和具體類實現(xiàn)。
- 對表達式進行解釋:根據(jù)語法規(guī)則解釋表達式蛙吏。
- 管理和執(zhí)行解釋器:將解釋器和表達式綁定鸦做,執(zhí)行解釋器解釋表達式泼诱。
迭代器模式(Iterator)
遍歷集合元素。
interface Iterator<T> {
fun hasNext(): Boolean
fun next(): T
}
class MyList<T>(private val items: MutableList<T>) : Iterable<T> {
override fun iterator(): Iterator<T> {
return MyListIterator()
}
private inner class MyListIterator : Iterator<T> {
private var index = 0
override fun hasNext(): Boolean {
return index < items.size
}
override fun next(): T {
return items[index++]
}
}
}
- 提供一種統(tǒng)一的方式訪問集合中的元素:迭代器模式為不同類型的集合提供了一致的遍歷接口耸袜,使得遍歷過程變得簡單和統(tǒng)一。
- 隱藏集合內部的實現(xiàn)細節(jié):迭代器模式將集合對象的遍歷操作與其內部結構分離蜈抓,避免了暴露集合的內部實現(xiàn)細節(jié)资昧,從而更容易維護和擴展集合荆忍。
- 支持同時遍歷多個集合對象:迭代器模式可以在同一時間遍歷多個集合對象格带,從而方便地對集合進行組合、過濾刹枉、排序等操作叽唱。
- 提供不同類型的迭代器:迭代器模式提供了不同類型的迭代器,例如正向迭代器微宝、反向迭代器、過濾迭代器蟋软、映射迭代器等镶摘,以滿足不同的遍歷需求嗽桩。
中介者模式(Mediator)
解耦多個對象之間的交互關系。
interface Mediator {
fun notify(sender: Colleague, event: String)
}
abstract class Colleague(val mediator: Mediator) {
abstract fun notify(event: String)
}
class ConcreteColleague1(mediator: Mediator) : Colleague(mediator) {
override fun notify(event: String) {
println("ConcreteColleague1 gets notified: $event")
}
}
class ConcreteColleague2(mediator: Mediator) : Colleague(mediator) {
override fun notify(event: String) {
println("ConcreteColleague2 gets notified: $event")
}
}
class ConcreteMediator : Mediator {
private lateinit var colleague1: ConcreteColleague1
private lateinit var colleague2: ConcreteColleague2
fun setColleague1(colleague1: ConcreteColleague1) {
this.colleague1 = colleague1
}
fun setColleague2(colleague2: ConcreteColleague2) {
this.colleague2 = colleague2
}
override fun notify(sender: Colleague, event: String) {
when (sender) {
colleague1 -> colleague2.notify(event)
colleague2 -> colleague1.notify(event)
}
}
}
fun main() {
val mediator = ConcreteMediator()
val colleague1 = ConcreteColleague1(mediator)
val colleague2 = ConcreteColleague2(mediator)
mediator.setColleague1(colleague1)
mediator.setColleague2(colleague2)
colleague1.notify("Hello, Colleague2!")
}
- 降低類之間的耦合:中介者模式通過將對象之間的通信集中在中介者中凄敢,從而減少了對象之間的直接依賴關系碌冶,降低了類之間的耦合度。
- 簡化對象之間的交互:中介者模式將對象之間的交互轉移至中介者涝缝,使得對象之間的交互變得簡單明了扑庞,易于理解和維護。
- 集中控制對象之間的交互:中介者模式通過集中控制對象之間的交互拒逮,可以更好地協(xié)調對象之間的行為罐氨,從而實現(xiàn)更復雜的系統(tǒng)功能。
- 提供靈活的擴展性:中介者模式使得系統(tǒng)易于擴展滩援,因為它可以很容易地增加栅隐、替換或刪除中介者對象和同事對象。
備忘錄模式(Memento)
保存對象狀態(tài)狠怨。
// 備忘錄類约啊,用于存儲 Originator 對象的狀態(tài)
data class Memento(val state: String)
// 原發(fā)器類,擁有一些需要保存狀態(tài)的屬性佣赖,并提供保存和恢復狀態(tài)的方法
class Originator(var state: String) {
fun createMemento(): Memento {
return Memento(state)
}
fun restoreMemento(memento: Memento) {
state = memento.state
}
}
// 管理者類恰矩,負責保存和恢復 Originator 對象的狀態(tài)
class Caretaker {
private var memento: Memento? = null
fun saveState(originator: Originator) {
memento = originator.createMemento()
}
fun restoreState(originator: Originator) {
memento?.let { originator.restoreMemento(it) }
}
}
- 記錄對象內部狀態(tài)
- 在不破壞封裝性的前提下保存和恢復對象狀態(tài)
觀察者模式(Observer)
當對象狀態(tài)發(fā)生變化時,通知它的依賴者憎蛤。
interface Observer {
fun update(value: Int)
}
class Observable {
private val observers = mutableListOf<Observer>()
var value: Int = 0
set(value) {
field = value
notifyObservers()
}
fun registerObserver(observer: Observer) {
observers.add(observer)
}
fun unregisterObserver(observer: Observer) {
observers.remove(observer)
}
private fun notifyObservers() {
observers.forEach { it.update(value) }
}
}
class ConcreteObserver(private val name: String) : Observer {
override fun update(value: Int) {
println("$name: The value has been updated to $value")
}
}
fun main() {
val observable = Observable()
val observer1 = ConcreteObserver("Observer 1")
val observer2 = ConcreteObserver("Observer 2")
observable.registerObserver(observer1)
observable.registerObserver(observer2)
observable.value = 5
observable.unregisterObserver(observer2)
observable.value = 10
}
- 主題與觀察者分離:主題對象(Subject)與觀察者對象(Observer)分離外傅,主題不需要知道觀察者是誰,而且可以動態(tài)添加或刪除觀察者俩檬。
- 狀態(tài)改變通知觀察者:當主題狀態(tài)改變時萎胰,會自動通知所有的觀察者對象,讓它們更新自己的狀態(tài)棚辽。
狀態(tài)模式(State)
根據(jù)對象的狀態(tài)技竟,改變對象的行為。
interface State {
fun doAction(context: Context)
}
class ConcreteStateA : State {
override fun doAction(context: Context) {
println("當前狀態(tài)為 A")
context.state = ConcreteStateB()
}
}
class ConcreteStateB : State {
override fun doAction(context: Context) {
println("當前狀態(tài)為 B")
context.state = ConcreteStateA()
}
}
class Context(var state: State) {
fun request() {
state.doAction(this)
}
}
fun main() {
val context = Context(ConcreteStateA())
context.request()
context.request()
context.request()
}
- 將對象的行為與其狀態(tài)分離:狀態(tài)模式的核心思想是將對象的行為與其狀態(tài)分離屈藐,使得同一行為在不同的狀態(tài)下有不同的實現(xiàn)榔组。通過將狀態(tài)封裝成獨立的類,可以將狀態(tài)的變化獨立于具體的對象联逻,從而降低對象之間的耦合性搓扯。
- 在運行時改變對象的狀態(tài),從而改變其行為:狀態(tài)模式允許在運行時改變對象的狀態(tài)包归,從而改變其行為锨推。在狀態(tài)模式中,對象的行為取決于其當前的狀態(tài),因此可以通過改變狀態(tài)來改變對象的行為换可。這種動態(tài)的行為改變使得狀態(tài)模式在某些場景下比較適用椎椰,例如游戲中的角色狀態(tài)等。
- 狀態(tài)之間可以相互轉換沾鳄,而不會影響對象的行為:狀態(tài)模式允許狀態(tài)之間相互轉換俭识,而不會影響對象的行為。在狀態(tài)模式中洞渔,狀態(tài)的轉換通常由對象的某些操作觸發(fā),例如用戶輸入等缚态。狀態(tài)轉換的過程通常由具體的狀態(tài)類來完成磁椒,這使得狀態(tài)之間的轉換更加靈活和可控。同時玫芦,由于狀態(tài)轉換并不影響對象的行為浆熔,因此狀態(tài)模式可以很好地應對狀態(tài)變化頻繁的場景。
策略模式(Strategy)
定義一系列算法桥帆,封裝每個算法医增,并使它們可以互換。
interface Strategy {
fun doOperation(num1: Int, num2: Int): Int
}
class AddStrategy : Strategy {
override fun doOperation(num1: Int, num2: Int): Int {
return num1 + num2
}
}
class SubtractStrategy : Strategy {
override fun doOperation(num1: Int, num2: Int): Int {
return num1 - num2
}
}
class Context(private val strategy: Strategy) {
fun executeStrategy(num1: Int, num2: Int): Int {
return strategy.doOperation(num1, num2)
}
}
fun main() {
val context = Context(AddStrategy())
println("10 + 5 = ${context.executeStrategy(10, 5)}")
context.strategy = SubtractStrategy()
println("10 - 5 = ${context.executeStrategy(10, 5)}")
}
- 將算法封裝成獨立的類:策略模式的核心思想是將算法封裝成獨立的類老虫,使得算法可以獨立于客戶端而變化叶骨。每個算法都由一個獨立的類來實現(xiàn),這些類都實現(xiàn)了一個共同的接口祈匙,從而可以在客戶端中互換使用忽刽。
- 在運行時選擇算法,實現(xiàn)動態(tài)切換:策略模式允許在運行時選擇算法夺欲,從而實現(xiàn)動態(tài)切換跪帝。客戶端可以在運行時選擇一個合適的算法些阅,然后將其傳遞給上下文類伞剑,上下文類會使用該算法進行運算。這種動態(tài)選擇算法的特性使得策略模式在某些場景下比較適用市埋,例如對于需要在多個算法之間動態(tài)選擇的場景黎泣。
- 避免使用大量的條件語句:策略模式避免了在客戶端中使用大量的條件語句,從而使代碼更加簡潔和易于維護腰素∑覆茫客戶端只需要知道有哪些算法可供選擇,并且如何選擇算法弓千,而不需要關心算法的實現(xiàn)細節(jié)衡便。這種解耦合的特性使得策略模式可以很好地應對算法變化頻繁的場景。
模板方法模式(Template Method)
定義一個算法的骨架,具體實現(xiàn)由子類完成镣陕。
abstract class Game {
abstract fun initialize()
abstract fun startPlay()
abstract fun endPlay()
fun play() {
initialize()
startPlay()
endPlay()
}
}
class CricketGame : Game() {
override fun initialize() {
println("Cricket Game Initialized! Start playing.")
}
override fun startPlay() {
println("Cricket Game Started. Enjoy the game!")
}
override fun endPlay() {
println("Cricket Game Finished!")
}
}
fun main() {
val game = CricketGame()
game.play()
}
- 封裝算法流程:模板方法模式封裝了一個算法流程谴餐,該算法流程由多個步驟組成,其中有些步驟是固定的呆抑,而有些步驟可以根據(jù)具體情況變化岂嗓。在模板方法模式中,固定的步驟通常是實現(xiàn)在抽象類中的鹊碍,而可變的步驟通常是由具體子類實現(xiàn)的厌殉。
- 提高代碼復用性:在模板方法模式中,算法流程被封裝在抽象類中侈咕,具體實現(xiàn)交由子類完成公罕。這種方式可以提高代碼的復用性,因為多個子類可以共享相同的算法流程耀销。
- 定義算法流程的骨架楼眷,具體實現(xiàn)交由子類完成:模板方法模式定義了一個算法流程的骨架,其中包含多個步驟熊尉,其中有些步驟是固定的罐柳,而有些步驟可以根據(jù)具體情況變化。在模板方法模式中狰住,固定的步驟通常是實現(xiàn)在抽象類中的张吉,而可變的步驟通常是由具體子類實現(xiàn)的。這種方式可以很好地分離出算法流程的通用部分和具體實現(xiàn)部分转晰,從而提高代碼的靈活性和可維護性芦拿。
訪問者模式(Visitor)
封裝對數(shù)據(jù)結構的操作。
interface ComputerPartVisitor {
fun visit(computer: Computer)
fun visit(keyboard: Keyboard)
fun visit(mouse: Mouse)
fun visit(printer: Printer)
}
interface ComputerPart {
fun accept(visitor: ComputerPartVisitor)
}
class Keyboard : ComputerPart {
override fun accept(visitor: ComputerPartVisitor) {
visitor.visit(this)
}
}
class Mouse : ComputerPart {
override fun accept(visitor: ComputerPartVisitor) {
visitor.visit(this)
}
}
class Printer : ComputerPart {
override fun accept(visitor: ComputerPartVisitor) {
visitor.visit(this)
}
}
class Computer : ComputerPart {
private val parts: Array<ComputerPart> = arrayOf(
Keyboard(),
Mouse(),
Printer()
)
override fun accept(visitor: ComputerPartVisitor) {
for (part in parts) {
part.accept(visitor)
}
visitor.visit(this)
}
}
class ComputerPartDisplayVisitor : ComputerPartVisitor {
override fun visit(computer: Computer) {
println("Displaying Computer.")
}
override fun visit(keyboard: Keyboard) {
println("Displaying Keyboard.")
}
override fun visit(mouse: Mouse) {
println("Displaying Mouse.")
}
override fun visit(printer: Printer) {
println("Displaying Printer.")
}
}
fun main() {
val computer: ComputerPart = Computer()
computer.accept(ComputerPartDisplayVisitor())
}
- 將數(shù)據(jù)結構與數(shù)據(jù)操作分離:在訪問者模式中查邢,數(shù)據(jù)結構與數(shù)據(jù)操作被分離開來蔗崎。數(shù)據(jù)結構是指一組對象的集合,而數(shù)據(jù)操作是指對這些對象的某些操作扰藕。通過將數(shù)據(jù)操作封裝在訪問者中缓苛,可以將數(shù)據(jù)結構與數(shù)據(jù)操作分離開來,從而更好地管理和組織代碼邓深。
- 增加新的操作不需要修改已有的類:在訪問者模式中未桥,數(shù)據(jù)結構中的每個對象都實現(xiàn)了一個accept方法,用于接受訪問者的訪問芥备。當需要增加一種新的操作時冬耿,只需要創(chuàng)建一個新的訪問者類,并實現(xiàn)該操作即可萌壳,而不需要修改已有的數(shù)據(jù)結構類亦镶。
- 將同一操作應用于不同的對象日月,實現(xiàn)操作的重用:在訪問者模式中,所有的訪問者都實現(xiàn)了相同的訪問方法缤骨,這意味著可以將同一操作應用于不同的對象爱咬,實現(xiàn)操作的重用。例如绊起,可以創(chuàng)建一個ComputerPartDisplayVisitor訪問者精拟,用于顯示計算機部件的信息,然后將該訪問者應用于不同的計算機部件對象虱歪,從而實現(xiàn)操作的重用蜂绎。