關於設計模式很對開發者都知道很重要,但陸陸續續學習過不少次,但學過的設計模式也基本忘了差很少,能記住的仍是以前使用的幾個基本的,如今藉此機會將23 中設計模式完整的梳理學習下,Java設計模式分類:java
建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。git
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。程序員
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式github
本篇全部的實例代碼和uml圖地址:JavaDesignModule算法
Factory Method模式原理來自意見產品的生產過程,從定義上的理解,將某一類事物按照面向對象的思想抽取成產品類,而後建立對應的工廠按照固定的模式建立相應的產品,至關於工廠裏的產品生產線,通常使用工廠模式時都伴隨着類似功能的類,這裏的工廠模式也主要是根據條件建立正確的類;編程
interface Product {
fun action()
}
class Car(val name : String) : Product { // 具體的產品類
override fun action() {
Log.e("Car -------- ","$name 是私家車!本身駕駛!")
}
}
複製代碼
interface ProductFactory {
fun createProduct(name: String):Product //建立Product抽象方法 } open class CarFactory : ProductFactory { // 具體的工廠類
override fun createProduct(name: String): Product {
return Car(name)
}
}
複製代碼
val car = CarFactory().createProduct("Audi") //建立具體工廠類,並調用方法建立產品
car.action()
複製代碼
意義 工廠模式利用抽象產品的轉型和統一管理產品的建立,將全部的實際產品和使用這些產品的代碼解耦,有利於代碼的擴展和維護設計模式
使用場景緩存
簡介 上面的工廠方法模式只是只針對單一類的產品,而對於多個產品時,若是繼續使用工廠模式則勢必要工廠類,這違背了開閉原則,此時須要使用抽象工廠模式,將工廠抽象出來,在工廠接口中定義多個產品的生產方法,而後讓每一個具體的工廠分別生產本身對應的一個或多個產品,從而造成不一樣的工廠羣和各自產品線的形式;數據結構
使用實例框架
abstract class Computer{
abstract fun action() } abstract class Phone(var name: String = "Phone") {
abstract fun call(number : String) } 複製代碼
class ComputerGreen : Computer() { // 電腦
override fun action() {
System.out.println(" Action by Green Computer !")
}
}
class PhoneGreen : Phone() { // 手機
override fun call(number: String) {
System.out.println(" Call $number by Green Phone !")
}
}
class ComputerRed : Computer() {
override fun action() {
System.out.println(" Action by Red Computer !")
}
}
class PhoneRed : Phone() {
override fun call(number: String) {
System.out.println(" Call $number by Red Phone !")
}
}
複製代碼
interface Factory {
fun createComputer() : Computer//生產電腦 fun createPhone() : Phone // 生產手機 } 複製代碼
class FactoryGreen : Factory {
override fun createComputer(): Computer {
return ComputerGreen() //生產Green電腦
}
override fun createPhone(): Phone {
return PhoneGreen() //生產Green手機
}
}
class FactoryRed : Factory {
override fun createComputer(): Computer {
return ComputerRed() //生產Red電腦
}
override fun createPhone(): Phone {
return PhoneRed() //生產Red手機
}
}
複製代碼
val factoryGreen = FactoryGreen() // 建立Green工廠
factoryGreen.createComputer()
factoryGreen.createComputer()
val factoryRed = FactoryRed() // 建立Red工廠
factoryRed.createComputer()
factoryRed.createComputer()
複製代碼
簡介 單例模式是開發中常用的基本模式,尤爲在一些工具類或框架的初始化中,如:Glide、EventBus等,它的最主要特性就是確保通常狀況下程序中只有一個實例;
功能角色
使用實例
class Singleton private constructor() {
companion object {
var singleton: Singleton? = null fun getIntance(): Singleton {
if (singleton == null) {
synchronized(Singleton::class.java) {
singleton = Singleton()
}
}
return singleton!!
}
}
}
複製代碼
class SingletonInner private constructor() {
class SingleHolder {
companion object {
val singletonInner = SingletonInner()
}
}
}
複製代碼
val single = Singleton.getIntance()
val singleInner = SingletonInner.SingleHolder.singletonInner
複製代碼
Builder設計模式是不少人第一個接觸的設計模式,就基本的Dialog就是使用Builder完成初始化,它利用在建立實例前使用Builder設置和保存配置的方式,極大的豐富了對象的使用場景和配置,並且使用中造成了鏈式調用;
功能角色 ![在這裏插入圖片描述](img-blog.csdnimg.cn/20190904160… =450x450)
使用實例:參見AlertDialog的使用
意義:簡化並統一對象的初始化過程,豐富對象的使用場景
使用場景 對於某個功能基本使用相同,但場景變化很是多時可使用Builder模式,將具體和功能和變換的配置解耦;
簡介 原型模式,從名稱的中就能大概讀出他的意思,它是利用已有的對象直接克隆出新對象,至關於自己的複製版,從而避免一系列的初始化和建立工做,而且能夠保持和現有對象徹底同樣的數據,對於原型自己須要具備調用clone()方法的能力,通常實現Cloneable接口便可;
功能角色
open class BaseProduct : Cloneable {
var name: String? = null
var price = 0
}
class CarProduct : BaseProduct(){
var coclor = "紅色"
fun createClone(): CarProduct { // 提供克隆方法
return super.clone() as CarProduct // 克隆並轉換對象
}
}
複製代碼
class FoodProduct(var food: Food) : BaseProduct(){
fun createClone(): FoodProduct {
val product = super.clone() as FoodProduct
product.food = food.createClone()// 內部存儲的對象也須要克隆並賦值
return product
}
}
複製代碼
open class Food( var price: Int = 0, var shop: String = "Shop" ) : Cloneable{ //由於淺複製的緣由,Food也要實現Cloneable而且提供複製方法
fun createClone(): Food {
return super.clone() as Food
}
}
複製代碼
val car = CarProduct()
car.name = "Audi"
car.price = 10000
val cerClone = car.createClone() // 克隆對象
Log.e("Car Name ---",cerClone.name)
Log.e("Car Price ---",cerClone.price.toString())
Log.e("Car Color ---",cerClone.coclor)
複製代碼
對於適配器咱們接觸作多的就是電源適配器,對於咱們身邊的電源通常都提供的是220V交流電,但不一樣的電器設備所需的電壓不一樣,那如何讓它們正常使用呢?這就須要適配器的存在,它能夠將200V的電壓轉換爲各自須要的電壓,並且不一樣的國家之間提供的電源也不一樣,那麼常常出差的人員可能就會配備多種不一樣的適配器,但它們的做用只有一個將現有不可直接使用的轉換爲可用的;
一樣的道理也適應在程序中,若是給你一個寫好的工具類,須要將它使用在其餘程序上,固然若是能直接使用最好,若是不能就須要在兩者之間構建適配器
假設目前只有一個輸出Int類型的工具類PrintInt,而提供的數據源是String類型,如今須要用適配器去讓PrintInt能夠執行;
open class PrintInt {
protected fun printInt(number : Int){
Log.e("輸出數字","number = $number")
}
}
複製代碼
interface PrintString {
fun print(message : String)// 聲明方法傳入字符串 } 複製代碼
class Adapter : PrintString ,PrintInt(){
override fun print(message : String) { //重寫方法
when(message){
"123" -> {printInt(123)}//將輸入的字符串調用printInt()輸出
}
}
}
複製代碼
val adapter = Adapter()
adapter.print("123")
複製代碼
假設如今有一個功能是按照行和列輸出字符串,如今有個需求要在輸出的字符串上下左右添加邊框,在不改變原來程序的基礎上使用裝飾者模式實現
abstract class Component {
abstract fun getRows(): Int // 獲取字符串行數 abstract fun getColumns(): Int // 獲取字符串列數 abstract fun getTextByRow(number: Int): String // 獲取對應的字符串 fun show() { // 顯示內容
val rows = getRows()
for (index in 0 until rows) {
System.out.println(getTextByRow(index))
}
}
}
複製代碼
class ConcerteComponent(val text: String) : Component() {
override fun getRows() = 1
override fun getColumns(): Int {
return text.length
}
override fun getTextByRow(number: Int): String {
return text
}
}
複製代碼
abstract class Decorator (val component: Component) : Component() 複製代碼
class ConcerteDecorator constructor(component: Component) : Decorator(component) {
override fun getRows(): Int {
return component.getRows() + 2
}
override fun getColumns(): Int {
return component.getColumns() + 2
}
override fun getTextByRow(number: Int): String {
return when (number) {
0 -> {"----------"}
getRows() - 1 -> {"----------"}
else -> {
"| ${component.getTextByRow(number)} |"
}
}
}
}
複製代碼
從上面的包裝類看出,它繼承了一樣的抽象類實現了一樣的抽象接口,在重寫的方法中主體仍是調用被包裝對象方法,而後在返回結果上增長處理;
val component = ConcerteComponent("HELLO")
val concerteDecorator = ConcerteDecorator(component)
concerteDecorator.show()
複製代碼
意義:更容易擴展原有程序的功能,而無需修改或影響原有程序
使用場景:當須要拓展某個對象功能時,且包裝對象和被包裝對象具備一致性時使用裝飾着模式進行擴展
代理模式是使用一個類似的對象來替代真實的對象,從而實現一系列的功能修改,比如現實中的中介代理同樣,當你須要某種需求時直接找代理,它們會幫你完成功能的實現;
interface PrintInterface { // 接口方法
fun setName(name: String) fun getName(): String fun print(content: String) } // 原有實現的功能方法 class RealPrint(private var nameReal: String) : PrintInterface {
override fun setName(name: String) {
action()
nameReal = name
}
override fun getName(): String {
action()
return nameReal
}
override fun print(content: String) {
Log.e("RealPrint = ", content)
}
private fun action(){}
}
複製代碼
如今已經有一個接口和對應實現的工具類RealPrint,但在RealPrint中的set和get兩個方法中每次都會調用額外的action()方法,如今的需求是要使用此類但又不要作額外的工做,此時使用代理模式修改set和get方法
class ProxyPrint( private var nameProxy: String) : PrintInterface {
private var realPrint: RealPrint? = null
override fun setName(name: String) {
realPrint?.setName(name)
nameProxy = name
}
override fun getName(): String {
return nameProxy
}
override fun print(content: String) {
initRealPrint()
realPrint?.print(content)
}
private fun initRealPrint() {
if (realPrint == null) {
realPrint = RealPrint(nameProxy)
}
}
}
複製代碼
在代理類ProxyPrint一樣繼承方法接口,並且內部保存着真實對象,在代理中修改了setName()和getName()方法,刪除調用的action()對象,在print()中由於要用到代理類的方法,因此建立代理類對象;
當某個工具類或方法須要修改時,爲了避免違反開閉原則可使用代理模式,將方法的修改部分和原始部分分離,互不影響;
外觀模式主要的功能解決類之間的依賴關係,以面向對象的思想編程,會將某個對象的功能方法封裝在一塊兒,但又是一個程序或模塊的執行須要依賴相關聯的介個類,那爲了避免讓類之間出現耦合就可採用外觀模式處理類的關係,從而實現類的解耦;
class Dashboard {
fun start() {
System.out.println("儀表盤啓動!")
}
fun stop(){
System.out.println("儀表盤中止!")
}
}
class Engine {
fun start() {
System.out.println("發動機啓動!")
}
fun stop(){
System.out.println("發動機中止!")
}
}
複製代碼
class Car() {
private var dashboard: Dashboard = Dashboard()
private var engine: Engine = Engine()
fun start() {
engine.start()
dashboard.start()
}
fun stop() {
engine.stop()
dashboard.stop()
}
}
複製代碼
val car = Car()
car.start()
car.stop()
複製代碼
簡介 橋接模式就是把使用和其具體實現分開,使他們能夠各自獨立的變化。橋接的用意是:將抽象化與實現化解耦,使得兩者能夠獨立變化,實際是將代碼的功能層次結構和實現層次結構相分離(這兩個概念後面會介紹)
功能角色
interface Implementer {
fun action(msg: String) fun print(msg: String) } class PrintImplementer : Implementer{
override fun action(msg: String) {
System.out.println(" Print Action = $msg")
}
override fun print(msg: String) {
System.out.println(" Print Print= $msg")
}
}
複製代碼
val implementer: Implementer = PrintImplementer() // 內部建立對象
fun action(msg: String) {
implementer.action(msg) // 調用真實實現的方法
}
fun print(msg: String) {
implementer.print(msg)
}
}
複製代碼
class AddFunction:Function() {
fun doSomething(msg: String) { // 外觀模式
action(msg)
print(msg)
}
}
複製代碼
簡介 組合模式定義:可以使容器和內容具備一致性,創造出遞歸結構的模式,可能定義比較抽象,它主要想形容一種數據結構,你可把它想像成文件和文件夾同樣,將文件夾當成容器,文件夾裏面便可以放文件也能夠放文件夾,此時就是容器和內容一致;
功能角色
使用實例:以文件夾結構爲例
abstract class Entry {
var parent: Entry? = null // 父文件夾
var name: String? = null //文件名稱
abstract fun getSize(): Int // 文件大小 abstract fun getAbslouteName() : String? // 文件路徑 abstract fun printStrign( msg: String) // 輸出信息 } 複製代碼
class Directory(val nameFile: String, val parentFile: Entry? = null) : Entry() {
private val arrayList = ArrayList<Entry>() // 保存容器內部文件
init {
name = nameFile
parent = parentFile
}
override fun getSize(): Int { // 遍歷獲取文件夾大小
val iterator = arrayList.iterator()
var size = 0
while (iterator.hasNext()){
size += iterator.next().getSize()
}
return size
}
override fun printStrign(msg: String) {
val iterator = arrayList.iterator()
while (iterator.hasNext()){
iterator.next().printStrign("$msg / $name")
}
}
override fun getAbslouteName(): String? {
if (parentFile == null) {
return name
}
return parentFile.getAbslouteName() +"/"+ name
}
fun add(entry: Entry) { // 向文件夾內添加文件
entry.parent = this
arrayList.add(entry)
}
}
複製代碼
class File(val nameFile: String, val sizeFile: Int = 0, var parentFile: Entry? = null) : Entry() {
override fun printStrign(msg: String) {
Log.e("======","$msg / $name")
}
override fun getAbslouteName(): String? {
if (parent == null) {
return name
}
return parent!!.getAbslouteName() +"/"+ name
}
init {
name = nameFile
parent = parentFile
}
override fun getSize(): Int = sizeFile
}
複製代碼
val rootD = Directory("root") // 建立跟目錄
val bin = Directory("bin",rootD) // 建立二級文件夾
val tem = Directory("tem",rootD)
val user = Directory("user",rootD)
val vi = File("vi",1000) // 建立文件
val latex = File("latex",500)
val tem_in = File("latex",800)
rootD.add(bin) // 添加文件
rootD.add(tem)
rootD.add(user)
bin.add(vi)
bin.add(latex)
tem.add(tem_in)
bin.add(tem)
複製代碼
簡介 享元模式:主要是利用緩存對象的方式實現對象的共享,從而減小對象的建立,在開發中也很常見,一般與Factory一塊兒使用,經過工廠產生數據前會線查看緩存信息,若是有則直接返回不然建立新對象並緩存;
功能角色
使用實例:JDBC鏈接池
意義:避免了對象的屢次建立,提升程序的總體性能
使用場景:每次使用都須要建立對象時,避免屢次建立可使用Flyweight模式
interface Iterator {
/** * 判斷是否有下一條數據 */
fun hasNext(): Boolean /** * 根據下標遍歷獲取數據 */ fun next() : Any } interface Congregation {
/** * 初始化迭代器 */
fun createIterator():Iterator } 複製代碼
class StudentIterator(private val congregation: StudentCongregation) : Iterator {
var index = 0
override fun hasNext(): Boolean {
return index < congregation.getSize()
}
override fun next(): Student {
val student = congregation.get(index)
index++
return student
}
}
複製代碼
class StudentCongregation : Congregation {
private val list by lazy { arrayListOf<Student>()}
override fun createIterator(): StudentIterator { // 建立具體的迭代器
return StudentIterator(this)
}
fun getSize():Int{
return list.size
}
fun add(student: Student){
list.add(student)
}
fun get(index : Int): Student{
return list[index]
}
}
複製代碼
val congregation = StudentCongregation()
for (id in 0..5) {
congregation.add(Student(id,"name = id",id * 10))
}
val iterator = congregation.createIterator()
while (iterator.hasNext()){
val student = iterator.next()
Log.e("=====","id = ${student.id} name = ${student.name} age = ${student.age}")
}
複製代碼
簡介 策略模式:對於某個需求時咱們可能會使用一些算法或邏輯來解決,但由於不一樣原用需求中算法須要被總體改變或替換時,通常的編程方式可能很難實現,但若是將每一個固定的邏輯封裝成策略,將它與總體系統分離,在執行須要時傳入對應的策略,此時邏輯就好像一個固定的模塊功能,便可實現無限次數的替換;
功能角色
使用實例
interface Strategy {
fun actionStrategy(number: Int): Int // 聲明的策略方法 } 複製代碼
class NumberStrategy : Strategy { // 第一種策略
override fun actionStrategy(number: Int): Int {
Log.e(" NumberStrategy = ", number.toString())
return number
}
}
class DoubleStrategy : Strategy { // 第二種策略
override fun actionStrategy(number: Int): Int {
return number * number
}
}
複製代碼
val player = Palyer(NumberStrategy())
player.play(5)
val playerD = Palyer(DoubleStrategy())
playerD.play(5)
複製代碼
簡介 模版模式:即全部的實現按照統一的方式進行,這裏統一的方式指固定的執行邏輯,模版模式首先在父類中藉助抽象方法實現邏輯的調用順序,而後在不一樣的子類中處理具體的抽象方法便可;
功能角色
使用實例:以公司職員一天的工做爲例
abstract class AbstractTemplate {
protected abstract fun weakUp() //起牀以後的事情 protected abstract fun enteringTheOffice() //進入辦公室 protected abstract fun openCompute() //打開電腦 protected abstract fun doJob() //工做 protected abstract fun goHome() //回家 fun actionForWorker() { // 方法中肯定了執行的邏輯
weakUp()
enteringTheOffice()
openCompute()
doJob()
goHome()
}
}
複製代碼
class DesignWorker(val name: String) : AbstractTemplate() { // 設計師工做
override fun weakUp() {
Log.e("$name ------","8:00 起牀了!")
Log.e("$name ------","8:10 刷牙洗臉!")
Log.e("$name ------","8:20 健身!")
Log.e("$name ------","8:40 吃早飯!")
Log.e("$name ------","9:00 開車出發!")
}
override fun enteringTheOffice() {
Log.e("$name ------","9:30 進入公司!")
Log.e("$name ------","9:35 泡了杯咖啡!")
}
override fun openCompute() {
Log.e("$name ------","9:40 看了場設計秀!")
}
override fun doJob() {
Log.e("$name ------","10:30 開始設計!")
}
override fun goHome() {
Log.e("$name ------","7:00 開車回家!")
}
}
class ITWorker(val name: String) : AbstractTemplate() { // 程序員工做
override fun weakUp() {
Log.e("$name ------","8:30 起牀了!")
Log.e("$name ------","9:00 刷牙洗臉,出發上班了!")
}
override fun enteringTheOffice() {
Log.e("$name ------","9:30 進入公司!")
Log.e("$name ------","9:35 接了杯白開水!")
}
override fun openCompute() {
Log.e("$name ------","9:40 打開它的Mac Pro !")
}
override fun doJob() {
Log.e("$name ------","9:40 開始一天的寫代碼 !")
}
override fun goHome() {
Log.e("$name ------","7:00 開始下班坐地鐵回家 !")
}
}
複製代碼
val itWorker = ITWorker("程序猿")
val design = DesignWorker("設計師")
itWorker.actionForWorker()
design.actionForWorker()
複製代碼
設計模式意義 模版模式的優勢在於只需在父類中編寫算法和處理流程,子類中無需編寫只需關注自身細節的處理,分離了總體邏輯和實現,提升代碼的可讀性也極大簡化了程序的修改和維護;
使用場景:像例子同樣按照總體邏輯但針對不一樣的目標處理時,便可採用模版模式定義實現模版,而後各自實現細節
interface Visitor {
fun visitor(file: FileElement) fun visitor(directory: DirectoryElement) } class ConcreteVisitor : Visitor {
override fun visitor(file: FileElement) {
Log.e("File=======", file.name)
}
override fun visitor(directory: DirectoryElement) {
Log.e("Directory=======", directory.name)
val iterator = directory.getInterator() // 對於文件夾循環遍歷內部文件
while (iterator.hasNext()) {
val file = iterator.next()
file.accept(this)
}
}
}
複製代碼
abstract class Element {
var parent: Element? = null
var name: String? = null abstract fun accept(visitor: Visitor) } 複製代碼
class FileElement(val nameFile: String, val sizeFile: Int = 0, var parentFile: Element? = null) : Element() { //File
override fun accept(visitor: Visitor) {
visitor.visitor(this)
}
init {
name = nameFile
parent = parentFile
}
}
class DirectoryElement(val nameFile: String, val parentFile: Element? = null) : Element() { //Directory
override fun accept(visitor: Visitor) {
visitor.visitor(this)
}
val arrayList = ArrayList<Element>()
init {
name = nameFile
parent = parentFile
}
fun add(entry: Element) {
entry.parent = this
arrayList.add(entry)
}
fun getInterator() = arrayList.iterator()
}
複製代碼
意義 訪問模式實現了數據結構和數據訪問的分離,對於數據結構穩定但訪問算法常常改變的場景,此時使用訪問模式分離可變的處理邏輯,更好的體現了開閉原則;
使用場景:數據結構穩定,但對數據的訪問和處理邏輯常常改變的場景
簡介 觀察者模式也是開發中常常接觸和使用的設計模式之一,在開源框架和Android系統組件中都有使用,典型表明RxJava、LiveData等;它的邏輯也很簡單主要將事件產生對象做爲被觀察者,將處理事件的邏輯做爲觀察者,兩者採用註冊或訂閱的方式關聯,當事件發送時調用觀察者的方法處理事件;
功能角色
使用實例:RxJava(Android框架源碼分析——RxJava源碼分析)
意義 將整個邏輯的處理分爲觀察者和被觀察者兩部分,被觀察者只需發送事件無需知道誰觀察則本身,而觀察者只需處理事件也無需知道事件的來源,此時被觀察者和觀察者能夠任意組合使用;
使用場景:須要都某個過程實現訂閱,當有新的消息通知自動處理時使用觀察者;
簡介 命令模式:將任務的執行向命令傳遞同樣發送,由指揮官發送命令,通過系列的傳達後到達目標士兵,士兵接收命令後執行,從這裏看出指揮官不必定知道他的命令最終通過多少傳遞和由誰執行,它只須要知道本身要下達那條命令,而士兵可能也不知道他的任務最初是誰的想法和命令,因此在程序中以此方式分離的發送命令和執行命令的角色;
功能角色
使用實例
interface Command {
fun action() } 複製代碼
class Receiver {
fun doAction(){......}
}
class ActionCommand(private val receiver: Receiver) : Command {
override fun action() {
receiver.doAction()
}
}
複製代碼
class Invoke(private val command: Command) {
fun doInvoke() {
command.action()
}
}
複製代碼
val receiver = Receiver()
val command = ActionCommand(receiver)
val invoke = Invoke(command)
invoke.doInvoke()
複製代碼
意義 將命令發送者和執行者分離實現代碼解耦,在使用時能夠爲每條命令選擇相應的執行者和發送者;
使用場景:對於請求和執行相分離的場景
class Memento(val money : Int) // 內部保存錢數
複製代碼
class User {
private var money = 0
private var memento: Memento = Memento(money)
fun getMemory() {
money = Random().nextInt()
}
fun createMementoInfo() { // 保存
memento = Memento(money)
}
fun restoreMementoInfo() { // 恢復
money = memento.money
}
}
複製代碼
abstract class Support {
private var next: Support? = null fun setNextSupport(support: Support): Support? { //設置下一個職責對象
next = support
return next
}
abstract fun action(number: Int) // 執行具體的操做 abstract fun canResolve(number: Int): Boolean // 判斷是否符合執行條件 fun doAction(number: Int) {
if (canResolve(number)) {
action(number)
} else if (next == null) {
doFailed()
} else {
next?.doAction(number)
}
}
fun doFailed() { // 當沒有方法處理時
System.out.println("No Support")
}
}
複製代碼
class SupportFirst : Support() {
override fun action(number: Int) {
System.out.println("SupportFirst")
}
override fun canResolve(number: Int): Boolean {
return number < 10
}
}
class SupportSecond(val numberMax : Int) : Support() {
override fun action(number: Int) {
System.out.println("SupportFirst")
}
override fun canResolve(number: Int): Boolean {
return number in 10..numberMax
}
}
複製代碼
val supportFirst = SupportFirst() // 建立職責對象
val supportSecond = SupportSecond(20)
val supportThird = SupportSecond(30)
supportFirst.setNextSupport(supportSecond).setNextSupport(supportThird) //設置職責鏈
supportFirst.action(25) // 調用方法
複製代碼
意義:經過使用多個職責對象造成責任鏈的形式,弱化了發送請求對象和處理請求對之間的關係,對於每一個職責類來看,只須要關注自身的職責即處理條件和處理方式,而整個職責鏈的設置和調用順序也能夠隨時修改和增減;
使用場景:當須要針對多種條件分別處理邏輯時使用職責模式;
簡介 狀態模式很好理解,對象的自己可能會有多種狀態存在,處在不一樣的狀態時對象的屬性和操做都有所不一樣,狀態模式就是指針對當前狀態下的全部操做進行編程,而後在使用時根據具體狀況切換狀態便可
功能角色
使用實例:以開關等爲例
interface State {
fun openLight(light: Light) // 開燈 fun closeLight(light: Light) // 關燈 } 複製代碼
class StateClose : State { // 關燈狀態
companion object {
val close = StateClose()
}
override fun openLight(light: Light) {
light.isLight = true
System.out.println("打開燈了")
light.steState(StateOpen.open)
}
override fun closeLight(light: Light) {
System.out.println("燈還沒開")
}
}
class StateOpen : State { // 開燈狀態
companion object {
val open = StateOpen()
}
override fun openLight(light: Light) {
System.out.println("燈已經開了")
}
override fun closeLight(light: Light) {
light.isLight = false
System.out.println("燈關閉了")
light.steState(StateClose.close)
}
}
複製代碼
class Light {
var isLight = false
private var state: State = StateClose.close fun steState(state: State) {
this.state = state
}
fun open() {
state.openLight(this)
}
fun close() {
state.closeLight(this)
}
}
複製代碼
val light = Light()
light.open()
light.open()
light.close()
light.close()
複製代碼
意義:使用狀態模式,將全部的操做以不一樣的狀態呈現,在每次操做完成後修改當前狀態,避免了每一個操做中都須要大量的條件判斷,提升程序的可讀性和擴展性
使用場景:針對不一樣狀態有不一樣操做的場景
class First : Action {
override fun action() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
class Second : Action {
override fun action() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
複製代碼
class Meidator {
val first = First()
val second = Second()
fun doAction() {
first.action()
second.action()
}
}
複製代碼
val meidator = Meidator()
meidator.doAction()
複製代碼
意義:將類之間的依賴關係解耦,提升程序的可維護性
使用場景:當現有的工具或代碼不能單獨實現邏輯時,此時使用中介者模式組合使用代碼,在中介者中實現代碼調用;
到此Java中的23種設計模式就介紹完畢了,對設計模式的學習相信不少人的感觸都是一致的,學習的時候發現設計模式很奇妙,也確實頗有設計感,但真正使用時仍是不太容易正確的選擇和使用,這也是對設計模式的理解不夠深刻吧,但願經過此23 中設計模式的學習能更好的掌握並使用設計模式;