目录
前言
责任链模式是一种行为设计模式,它允许将请求的发送者和接收者解耦,让多个对象都有机会处理这个请求。在这个模式中,这些对象形成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
装饰器模式是一种结构型设计模式,允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持原类方法签名完整性的前提下,提供了额外的功能。
工厂方法,提供了一种创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使一个类的实例化延迟到其子类。简而言之,工厂方法让类把实例化推迟到子类进行。在工厂方法模式中,不直接通过 new
关键字来创建对象,而是通过一个特定的方法(即工厂方法)来创建对象。这个方法通常由一个接口定义,并由子类实现,这样就可以在不直接依赖具体类的情况下生成对象,增加了代码的灵活性和可扩展性。
回退策略是一种错误处理或容错的设计模式,用于应对操作失败或异常情况。当一个操作失败时,系统将尝试一个或多个备用方案,以确保系统的稳定运行或至少能够优雅地处理错误。
正文
责任链模式优点
- 降低耦合度。它将请求的发送者和接收者解耦。
- 增强了给对象指派职责的灵活性。通过改变链内的成员或调整它们的次序,允许动态地新增或删除责任。
- 增加了新的请求处理类很方便。
责任链模式示例代码
有一个日志记录的系统,根据日志的等级将信息输出到不同的地方:控制台、文件、网络等。‘
首先,定义日志等级和处理者抽象类:
enum class LogLevel {
INFO, DEBUG, ERROR
}
abstract class Logger(protected var level: LogLevel) {
private var nextLogger: Logger? = null
fun setNextLogger(nextLogger: Logger): Logger {
this.nextLogger = nextLogger
return this
}
fun logMessage(level: LogLevel, message: String) {
if (this.level <= level) {
write(message)
}
nextLogger?.logMessage(level, message)
}
abstract protected fun write(message: String)
}
配置责任链并使用:
fun main() {
val consoleLogger = ConsoleLogger(LogLevel.INFO)
val fileLogger = FileLogger(LogLevel.DEBUG).setNextLogger(consoleLogger)
val networkLogger = NetworkLogger(LogLevel.ERROR).setNextLogger(fileLogger)
networkLogger.logMessage(LogLevel.INFO, "This is an informational message.")
networkLogger.logMessage(LogLevel.DEBUG, "This is a debug message.")
networkLogger.logMessage(LogLevel.ERROR, "This is an error message.")
}
省略了ConsoleLogger等...logger的实现代码。
装饰器模式示例代码
有一个简单的咖啡制作过程,我们希望能够动态地为咖啡添加各种调料,如牛奶、糖等。
首先,定义一个咖啡接口:
interface Coffee {
fun cost(): Double
fun ingredients(): String
}
实现基础咖啡类:
class BasicCoffee : Coffee {
override fun cost() = 1.0
override fun ingredients() = "Coffee"
}
创建装饰器基类:
abstract class CoffeeDecorator(protected val coffee: Coffee) : Coffee {
override fun cost(): Double = coffee.cost()
override fun ingredients(): String = coffee.ingredients()
}
实现具体的装饰器类:
class WithMilk(coffee: Coffee) : CoffeeDecorator(coffee) {
override fun cost(): Double = super.cost() + 0.5
override fun ingredients(): String = super.ingredients() + ", Milk"
}
class WithSugar(coffee: Coffee) : CoffeeDecorator(coffee) {
override fun cost(): Double = super.cost() + 0.2
override fun ingredients(): String = super.ingredients() + ", Sugar"
}
工厂方法组成
- 产品接口:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现了产品接口的类,定义了要生成的具体产品的对象。
- 创建者(Creator)类:声明了工厂方法,该方法返回一个产品类型的对象。创建者类的子类通常提供这个方法的实现。
- 具体创建者:重写工厂方法以返回一个具体产品实例。
工厂模式示例代码
定义一个日志记录系统,可以根据不同的情况记录到不同的地方(例如,控制台、文件)。使用工厂方法模式来实现这一点。
首先,定义日志记录器接口和几种具体的日志记录器:
interface Logger {
fun log(message: String)
}
class ConsoleLogger : Logger {
override fun log(message: String) {
println("Log to console: $message")
}
}
class FileLogger : Logger {
override fun log(message: String) {
println("Log to file: $message")
}
}
接下来,定义一个创建者抽象类和具体的创建者类:
abstract class LoggerFactory {
abstract fun createLogger(): Logger
fun getLogger(): Logger {
return createLogger()
}
}
class ConsoleLoggerFactory : LoggerFactory() {
override fun createLogger(): Logger = ConsoleLogger()
}
class FileLoggerFactory : LoggerFactory() {
override fun createLogger(): Logger = FileLogger()
}
使用如下:
fun main() {
val consoleLoggerFactory = ConsoleLoggerFactory()
val consoleLogger = consoleLoggerFactory.getLogger()
consoleLogger.log("This is a console log.")
val fileLoggerFactory = FileLoggerFactory()
val fileLogger = fileLoggerFactory.getLogger()
fileLogger.log("This is a file log.")
}
回退策略示例代码
fun fetchData(): String {
if (Random.nextInt(10) < 7) {
throw Exception("Network Error")
}
return "Data from server"
}
fun fetchDataWithFallbackStrategy(attempts: Int = 3): String {
var lastException: Exception? = null
for (i in 1..attempts) {
try {
return fetchData()
} catch (e: Exception) {
lastException = e
println("Attempt $i failed: ${e.message}")
}
}
return "Fallback data"
}
如上就是应用了回退策略的代码,有百分之70的概率NetWorkError,在attempts次数里多次尝试,如果均NetWorkError还能返回一个回退数据。
结尾
设计模式的英文是什么?Design pattern,这是一个非常之准确的词汇,个人认为比中文翻译好太多了。
Patten中文释义:. n. 模式;图案;样品. vt. 模仿pattern往往意味着是一种既定的准则,从它的动词可以看到,他有模仿的意思,也就是说,这样的代码设计,是一系列前人留下的经验,只要跟着这样写代码,往往能够让你的代码,更加简洁,更加健壮,更加优雅!
我觉得他应该有个意译的名字,叫做:代码设计的最佳实践!