Android进阶知识树——23种设计模式详解

关于设计模式很对开发者都知道很重要,但陆陆续续学习过很多次,但学过的设计模式也基本忘了差不多,能记住的还是之前使用的几个基本的,现在借此机会将23 中设计模式完整的梳理学习下,Java设计模式分类:

  • 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式

本篇所有的实例代码和uml图地址:JavaDesignModule

1、Factory Method模式
  • 简介:用Template Method的模式来构建生成实例的工厂,这就是工厂方法模式;

Factory Method模式原理来自意见产品的生产过程,从定义上的理解,将某一类事物按照面向对象的思想抽取成产品类,然后创建对应的工厂按照固定的模式创建相应的产品,相当于工厂里的产品生产线,一般使用工厂模式时都伴随着相似功能的类,这里的工厂模式也主要是根据条件创建正确的类;

  • 设计模式的意义
  1. 工厂模式实现了对所有产品创建的管理,将产品和具体使用产品的类解耦
  2. 利于程序的扩展,有新添加产品时,只需要分别实现对应的产品类和工厂类即可
  • 功能角色
    在这里插入图片描述
  1. Product:抽象的产品类,内部定义产品的功能属性和方法;
  2. ObjectProduct:具体实现的产品类,针对具体的产品实现具体的功能;
  3. ProductFactory:抽象工厂类,定义创建产品的抽象方法;
  4. ObjectProductFactory:实现抽象工厂类,重写抽象方法根据设定的条件创建具体的产品;
  • 使用
  1. 创建抽象产品类,并实现具体的产品和方法
interface Product {
    
    fun action()
}
class Car(val name : String) : Product {
    // 具体的产品类
    override fun action() {
   
        Log.e("Car -------- ","$name 是私家车!自己驾驶!")
    }
}
  1. 创建产品工厂接口,并创建实现类
interface ProductFactory {
   
    fun createProduct(name: String):Product //创建Product抽象方法
}
open class CarFactory : ProductFactory {
    // 具体的工厂类
    override fun createProduct(name: String): Product {
   
        return Car(name)
    }
}
  1. 使用工厂模式
val car = CarFactory().createProduct("Audi") //创建具体工厂类,并调用方法创建产品
car.action()
  • 意义
    工厂模式利用抽象产品的转型和统一管理产品的创建,将所有的实际产品和使用这些产品的代码解耦,有利于代码的扩展和维护

  • 使用场景

  1. 针对某个抽象产品有多种实现时,可以使用工厂方法分别实现不同的产品类,然后再工厂中按需求创建产品;
2、Abstract Factory模式
  • 简介
    上面的工厂方法模式只是只针对单一类的产品,而对于多个产品时,如果继续使用工厂模式则势必要工厂类,这违背了开闭原则,此时需要使用抽象工厂模式,将工厂抽象出来,在工厂接口中定义多个产品的生产方法,然后让每个具体的工厂分别生产自己对应的一个或多个产品,从而形成不同的工厂群和各自产品线的形式;

  • 使用实例

  1. 定义两个产品Computer和Phone
abstract class Computer{
   
    abstract fun action()
}

abstract class Phone(var name: String = "Phone") {
   
    abstract fun call(number : String)
}
  1. 目前分别有两家工厂Green和Red生产,现在实现它们各自对应的产品类
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 !")
    }
}
  1. 创建工厂接口,声明创建两个产品的方法
interface Factory {
   
    fun createComputer() : Computer//生产电脑
    fun createPhone() : Phone // 生产手机
}
  1. 实现两个各自的工厂类,分别创建自己的产品
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手机
    }
}
  1. 使用抽象工厂
val factoryGreen = FactoryGreen() // 创建Green工厂
factoryGreen.createComputer()
factoryGreen.createComputer()

val factoryRed = FactoryRed() // 创建Red工厂
factoryRed.createComputer()
factoryRed.createComputer()
  • 意义:在工厂模式的基础上将工厂也抽象出来,这样可以实现多个工厂和多个产品的存在,当增加工厂个产品时直接创建其扩展类即可,无需修改原来的代码
  • 使用场景:针对多种产品和多个分类时,可以使用抽象工厂模式统一管理所有产品
3、Singleton模式
  • 简介
    单例模式是开发中经常使用的基本模式,尤其在一些工具类或框架的初始化中,如:Glide、EventBus等,它的最主要特性就是确保一般情况下程序中只有一个实例;

  • 功能角色
    在这里插入图片描述

  • 使用实例

  1. 双重判断方式提供单例
class Singleton private constructor() {
   
    companion object {
   
        var singleton: Singleton? = null
        fun getIntance(): Singleton {
   
            if (singleton == null) {
   
                synchronized(Singleton::class.java) {
   
                    singleton = Singleton()
                }
            }
            return singleton!!
        }
    }
}
  1. 静态内部类方式
class SingletonInner private constructor() {
   
    class SingleHolder {
   
        companion object {
   
            val singletonInner = SingletonInner()
        }
    }
}
  • 使用单例模式
val single = Singleton.getIntance()
val singleInner = SingletonInner.SingleHolder.singletonInner
  • 意义:对于经常需要使用但每次需要获取的对象,或初始化比较复杂的对象使用单例提供,节省获取或初始化的时间;
  • 使用场景:想确保程序中只存在一个实例存在;
4、Builder模式
  • 简介

Builder设计模式是很多人第一个接触的设计模式,就基本的Dialog就是使用Builder完成初始化,它利用在创建实例前使用Builder设置和保存配置的方式,极大的丰富了对象的使用场景和配置,而且使用中形成了链式调用;

  • 功能角色
    在这里插入图片描述

  • 使用实例:参见AlertDialog的使用

  • 意义:简化并统一对象的初始化过程,丰富对象的使用场景

  • 使用场景
    对于某个功能基本使用相同,但场景变化非常多时可以使用Builder模式,将具体和功能和变换的配置解耦;

5、Prototype模式
  • 简介
    原型模式,从名称的中就能大概读出他的意思,它是利用已有的对象直接克隆出新对象,相当于本身的复制版,从而避免一系列的初始化和创建工作,并且可以保持和现有对象完全一样的数据,对于原型本身需要具有调用clone()方法的能力,一般实现Cloneable接口即可;

  • 功能角色
    在这里插入图片描述

  1. Prototype:原型接口,继承Cloneable接口
  2. PrototypeImpl:原型接口的实现类,也是克隆新对象的原始标本
  • 使用实例
  1. 创建类实现Cloneable接口,在具体的类中调用clone()方法克隆对象
open class BaseProduct : Cloneable {
   
    var name: String? = null
    var price = 0
}

class CarProduct : BaseProduct(){
   
    var coclor = "红色"
    fun createClone(): CarProduct {
    // 提供克隆方法
        return super.clone() as CarProduct // 克隆并转换对象
    }
}
  1. 对于对象嵌套的原型,即需要克隆的队像中持有别的对象;
class FoodProduct(var food: Food) : BaseProduct(){
   
    fun createClone(): FoodProduct {
   
        val product = super.clone() as FoodProduct 
        product.food = food.createClone()// 内部存储的对象也需要克隆并赋值
        return product
    }
}
  1. 上面代码中的FoodProduct中保存了Food对象,在克隆时如果要确保对象数据一致,就必须让food对象也克隆一份,所以Food对象也要实现Cloneable接口
open class Food(
    var price: Int = 0,
    var shop: String = "Shop"
) : Cloneable{
    //因为浅复制的原因,Food也要实现Cloneable并且提供复制方法
    fun createClone(): Food {
   
        return super.clone() as Food
    }
}
  1. 使用原型模式
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)
  • 意义:避免对象的创建,而且可以复制出一份和当前对象数据一致的副本
6、Adapter模式
  • 简介

对于适配器我们接触做多的就是电源适配器,对于我们身边的电源一般都提供的是220V交流电,但不同的电器设备所需的电压不同,那如何让它们正常使用呢?这就需要适配器的存在,它可以将200V的电压转换为各自需要的电压,而且不同的国家之间提供的电源也不同,那么经常出差的人员可能就会配备多种不同的适配器,但它们的作用只有一个将现有不可直接使用的转换为可用的;

同样的道理也适应在程序中,如果给你一个写好的工具类,需要将它使用在其他程序上,当然如果能直接使用最好,如果不能就需要在二者之间构建适配器

  • 功能角色
    在这里插入图片描述
  1. Target:创建抽象接口,在接口声明目标要调用的方法
  2. Adaptee:本来存在的工具类,即想要适配后调用的类
  3. Ad
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值