• 设计模式--kotlin&java


    一、前言

    二、单例模式

    饿汉模式

    java

    1. //单例模式 -- 饿汉式
    2. public class Singleton {
    3. //随着对象的创建就去new
    4. private static Singleton mInstance = new Singleton();
    5. private Singleton() {
    6. }
    7. public static Singleton getInstance(){
    8. return mInstance;
    9. }
    10. }

    kotlin

    1. object Singleton {
    2. }

    总结:

    饿汉模式在类被初始化时就在内存中创建了对象,以空间换时间的方式创建对象,不存在线程安全问题,对象只要类被初始化就会被创建,比较占内存

    懒汉模式

    最初模型

    java

    1. //单例模式 -- 懒汉式
    2. public class Singleton {
    3. //只有使用的时候才去new对象,更加高效,
    4. private static Singleton mInstance ;
    5. private Singleton() {
    6. }
    7. public static Singleton getInstance(){
    8. if (mInstance == null){
    9. //会出现多线程并发问题
    10. mInstance = new Singleton();
    11. }
    12. return mInstance;
    13. }
    14. }

    kotlin

    1. //懒汉式
    2. //构造函数私有化
    3. class Singleton private constructor() {
    4. companion object {
    5. private var instance: Singleton? = null
    6. get() {
    7. if (field == null) {
    8. field = Singleton()
    9. }
    10. return field
    11. }
    12. fun get(): Singleton {
    13. return instance!!
    14. }
    15. }
    16. }

    总结:

    • 在方法被调用时才会创建这个对象,以时间换空间
    • 存在风险:多线程并发调用时,实例可能创建多份
    解决懒汉式在多线程下的并发问题 -- 加锁

    java

    1. //单例模式 -- 懒汉式
    2. public class Singleton {
    3. private static Singleton mInstance;
    4. private Singleton() {
    5. }
    6. //解决懒汉式多线程并发问题,但是会出现效率低的问题,每次获取都要经过同步锁的判断
    7. public static synchronized Singleton getInstance(){
    8. if (mInstance == null){
    9. mInstance = new Singleton();
    10. }
    11. return mInstance;
    12. }
    13. }

    kotlin

    1. class Singleton private constructor() {
    2. companion object {
    3. private var instance: Singleton? = null
    4. get() {
    5. if (field == null) {
    6. field = Singleton()
    7. }
    8. return field
    9. }
    10. @Synchronized
    11. fun get(): Singleton {
    12. return instance!!
    13. }
    14. }
    15. }

    总结:

    • 通过Synchronized关键字来修饰静态方法,保证多个线程并发调用时只有一个线程进入到方法内部,当一个线程调用时,其他线程被阻隔在方法外边,来保证实例的唯一性
    • 解决了懒汉式多线程并发问题,但是会出现并发调用效率低的问题,每次获取都要经过同步锁的判断,
    解决每次获取都要经过同步锁判断导致的线程低的问题  -- 双重检验

    java

    1. //单例模式 -- 懒汉式
    2. public class Singleton {
    3. private volatile static Singleton mInstance;
    4. private Singleton() {
    5. }
    6. //既保证了线程安全,效率也是比较高,但是会出现指令重排序问题
    7. public static Singleton getInstance() {
    8. if (mInstance == null) {
    9. synchronized (Singleton.class) {
    10. if (mInstance == null) {
    11. mInstance = new Singleton();
    12. }
    13. }
    14. }
    15. return mInstance;
    16. }
    17. }

    kotlin

    1. class Singleton private constructor() {
    2. companion object {
    3. val INSTANCE: Singleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
    4. Singleton()
    5. }
    6. }
    7. }

    总结:

    • 提效,第一个判空,是在instance创建的情况下避免进入同步代码块,提供程序并发效率
    • 保证唯一性,当多个线程并发访问对象时,会遇到同步代码块,只能有一个线程执行,其他线程必须等待当前线程完成之后才能继续执行 
    • 但是需要增加一个volatile关键字

    volatile关键字禁止重排序:

            多线程进入到getInstance之后,线程A在自己的工作线程里面创建了自己的实例,此时还未同步到主存中,A已经跳出了代码块,是否了锁,当B线程进行代码块,获得了同步代码块的执行时间,判断instance==null,这时B线程还是会去创建这个实力,所以它并不能百分百的保证实例的唯一性,内存空间会被重排,加上volatile关键字来保证实例的可见性,防止指令重排序

    静态内部类模式

    java

    1. //静态内部类
    2. public class singleton {
    3. private static class singletonProvider {
    4. private static singleton instance = new singleton();
    5. }
    6. private singleton() {
    7. }
    8. public static singleton getInstance() {
    9. return singletonProvider.instance;
    10. }
    11. }

    kotlin

    1. class Singleton {
    2. companion object {
    3. val instance = SingletonProvider.holder
    4. }
    5. private object SingletonProvider {
    6. val holder = singleton()
    7. }
    8. }

    总结:

            推荐使用,既能保证线程安全,又能保证实例的唯一性,还能实现单例延时的实例化,外部类加载时并不会立即加载内部类,内部类不被加载也就不会实例化instance,因此不会占用空间,只有调用getInstance,访问singletonProvider.instance时,才会去实例化SingletonProvider,才会创建Singleton的实例

    三、装饰器模式

    java

    1. /**
    2. * 抽象组件
    3. */
    4. public interface Animal {
    5. void eat();
    6. }
    7. /**
    8. * 被装饰者组件
    9. */
    10. public class Panda implements Animal {
    11. @Override
    12. public void eat() {
    13. System.out.println("吃什么?");
    14. }
    15. }
    16. /**
    17. * 抽象装饰器
    18. */
    19. public abstract class Food implements Animal{
    20. Animal animal;
    21. public Food(Animal animal) {
    22. this.animal = animal;
    23. }
    24. @Override
    25. public void eat() {
    26. animal.eat();
    27. }
    28. }
    29. /**
    30. * 具体装饰器
    31. */
    32. public class BarrotFood extends Food{
    33. public BarrotFood(Animal animal) {
    34. super(animal);
    35. }
    36. @Override
    37. public void eat() {
    38. super.eat();
    39. System.out.println("可以吃胡萝卜");
    40. }
    41. }
    42. /**
    43. * 具体装饰器
    44. */
    45. public class BambooFood extends Food{
    46. public BambooFood(Animal animal) {
    47. super(animal);
    48. }
    49. @Override
    50. public void eat() {
    51. super.eat();
    52. System.out.println("可以吃竹子");
    53. }
    54. }
    55. public class Client {
    56. public static void main(String[] args) {
    57. Panda panda = new Panda();
    58. BarrotFood barrotFood = new BarrotFood(panda);
    59. BambooFood bambooFood = new BambooFood(barrotFood);
    60. bambooFood.eat();
    61. }
    62. }
    63. /**
    64. * 测试类
    65. */
    66. public class Client {
    67. public static void main(String[] args) {
    68. Panda panda = new Panda();
    69. BarrotFood barrotFood = new BarrotFood(panda);
    70. BambooFood bambooFood = new BambooFood(barrotFood);
    71. bambooFood.eat();
    72. }
    73. }

    Kotlin

    1. fun Panda.bamboo(decorator:()->Unit){
    2. eat()
    3. println("可以吃竹子")
    4. decorator()
    5. }
    6. fun Panda.carrot(decorator:()->Unit){
    7. println("可以吃胡萝卜")
    8. decorator()
    9. }
    10. fun main() {
    11. Panda().run {
    12. bamboo { carrot { } }
    13. }
    14. }

    四、建造者模式

    Java

    1. public class Pen {
    2. private Builder builder;
    3. public Pen(Builder builder) {
    4. this.builder = builder;
    5. }
    6. public void write() {
    7. System.out.println("color:" + builder.color + " width:" + builder.width + " round:" + builder.round);
    8. }
    9. public static class Builder {
    10. private String color = "white";
    11. private float width = 1.0f;
    12. private boolean round = false;
    13. public Builder setColor(String color) {
    14. this.color = color;
    15. return this;
    16. }
    17. public Builder setWidth(float width) {
    18. this.width = width;
    19. return this;
    20. }
    21. public Builder setRound(boolean round) {
    22. this.round = round;
    23. return this;
    24. }
    25. public Pen build() {
    26. return new Pen(this);
    27. }
    28. }
    29. }
    30. public class Client {
    31. public static void main(String[] args) {
    32. Pen.Builder builder = new Pen.Builder();
    33. builder.setColor("").setRound(true).setWidth(1f).build().write();
    34. }
    35. }

    Kotlin

    1. class Penk {
    2. var color = "white"
    3. var width = 1.0f
    4. var round = false
    5. fun write() {
    6. println("color:${color} width:${width} round:${round}")
    7. }
    8. }
    9. fun main() {
    10. val pen = Penk()
    11. //使用with来实现建造者模式
    12. with(pen) {
    13. color = ""
    14. width = 1f
    15. round = true
    16. }
    17. pen.write()
    18. //使用apply来实现建造者模式
    19. pen.apply {
    20. color = ""
    21. width = 2f
    22. round = false
    23. write()
    24. }
    25. }

    五、适配器模式

    把一个类的接口变成客户端所期待的另一个接口,从而使因接口不匹配的两个模块或者部件能在一起工作。

    分为类适配器模式

    Android中源码中的使用:ListView、RecyclerView

    优点:

    • 将目标类和适配器类解耦
    • 增加了类的透明性和复用性
    • 灵活性和扩展性好,符合开闭原则

    结构:

    • Target:目标角色(所期待得到的接口)
    • Adapter:适配器类
    • Adaptee:适配器类(现在需要适配的接口)
    • Client:客户类

    类适配器模式

    1. interface Target {
    2. fun request1()
    3. fun request2()
    4. }
    5. //适配者类
    6. open class Adaptee {
    7. fun request1() {
    8. println("Adaptee:request1")
    9. }
    10. }
    11. //适配器类
    12. class AdapterClass : Adaptee(), Target {
    13. override fun request2() {
    14. println("AdapterClass:request2")
    15. }
    16. }
    17. class Client {
    18. fun main() {
    19. //类适配器
    20. val adapterClass = AdapterClass()
    21. adapterClass.apply {
    22. request1()
    23. request2()
    24. }
    25. }
    26. }

    对象适配器模式

    使用委派替代继承

    1. //适配者类
    2. open class Adaptee {
    3. fun request1() {
    4. println("Adaptee:request1")
    5. }
    6. }
    7. //对象适配器
    8. class AdapterObj(private var adaptee:Adaptee) :Target{
    9. override fun request1() {
    10. adaptee.request1()
    11. }
    12. override fun request2() {
    13. println("AdapterObj:request2")
    14. }
    15. }
    16. class Client {
    17. fun main() {
    18. //对象适配器
    19. val adaptee = Adaptee()
    20. val adapterObj = AdapterObj(adaptee)
    21. adapterObj.apply {
    22. request1()
    23. request2()
    24. }
    25. }
    26. }

    优点:可以适配多个目标

    六、架构、框架与设计模式

    软件架构:

    架构不是软件,它是抽象的,是一种设计方案,是一个蓝图

    软件框架:

    框架(framework)是整个或部分系统的可重用设计,表现为一组抽象架构及构件实例间交互的方法

    框架是一种特殊的软件,它并不能提供完整无缺的解决方案,而是为你构建解决方案提供良好的基础

    设计模式:

    在软件工程中,设计模式是对软件设计中普遍存在的各种问题,所提出的解决方案。设计模式是解决局部问题的方法

  • 相关阅读:
    JAVA集合问答
    MySQL的多表间关系
    SwiftUI Swift基础之Swift 数组的多种方法(教程含源码)
    R 和 Python用于统计学分析,哪个更好?
    无人机培训机构所需资质证书详解
    【Java 进阶篇】MySQL 数据控制语言(DCL):管理用户权限
    精通C语言:打造高效便捷的通讯录管理系统
    MySQL基础三问:底层逻辑、正在执行、日志观察
    天坑,这样一个lambda随机取数据也有Bug
    第四十六章 命名空间和数据库 - 系统提供的数据库
  • 原文地址:https://blog.csdn.net/weixin_42277946/article/details/136279347