设计模式--kotlin&java

时间:2024-03-06 14:24:15

一、前言

二、单例模式

饿汉模式

java

//单例模式 -- 饿汉式
public class Singleton {
    //随着对象的创建就去new 
    private static Singleton mInstance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance(){
        return mInstance;
    }
}

kotlin

object Singleton {

}

总结:

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

懒汉模式

最初模型

java

//单例模式 -- 懒汉式
public class Singleton {
    //只有使用的时候才去new对象,更加高效,
    private static Singleton mInstance ;

    private Singleton() {
    }

    
    public static Singleton getInstance(){
        if (mInstance == null){
            //会出现多线程并发问题
            mInstance = new Singleton();
        }
        return mInstance;
    }
}

kotlin

//懒汉式
//构造函数私有化
class Singleton private constructor() {

    companion object {
        private var instance: Singleton? = null
            get() {
                if (field == null) {
                    field = Singleton()
                }
                return field
            }

        fun get(): Singleton {
            return instance!!
        }
    }
}

总结:

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

java

//单例模式 -- 懒汉式
public class Singleton {
    private static Singleton mInstance;

    private Singleton() {
    }

    //解决懒汉式多线程并发问题,但是会出现效率低的问题,每次获取都要经过同步锁的判断
    public static synchronized Singleton getInstance(){
        if (mInstance == null){
            mInstance = new Singleton();
        }
        return mInstance;
    }   
}

kotlin

class Singleton private constructor() {

    companion object {
        private var instance: Singleton? = null
            get() {
                if (field == null) {
                    field = Singleton()
                }
                return field
            }

        @Synchronized
        fun get(): Singleton {
            return instance!!
        }
    }
}

总结:

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

java

//单例模式 -- 懒汉式
public class Singleton {
    private volatile static Singleton mInstance;

    private Singleton() {
    }

   //既保证了线程安全,效率也是比较高,但是会出现指令重排序问题
    public static Singleton getInstance() {
        if (mInstance == null) {
            synchronized (Singleton.class) {
                if (mInstance == null) {
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}

kotlin

class Singleton private constructor() {

    companion object {
        val INSTANCE: Singleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Singleton()
        }
    }
}

总结:

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

volatile关键字禁止重排序:

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

静态内部类模式

java

//静态内部类
public class singleton {
    private static class singletonProvider {
        private static singleton instance = new singleton();
    }

    private singleton() {
    }

    public static singleton getInstance() {
        return singletonProvider.instance;
    }
}

kotlin

class Singleton {

    companion object {
        val instance = SingletonProvider.holder
    }

    private object SingletonProvider {
        val holder = singleton()
    }
}

总结:

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

三、装饰器模式

java

/**
 * 抽象组件
 */
public interface Animal {
    void eat();
}

/**
 * 被装饰者组件
 */
public class Panda implements Animal {
    @Override
    public void eat() {
        System.out.println("吃什么?");
    }
}

/**
 * 抽象装饰器
 */
public abstract class Food implements Animal{
    Animal animal;

    public Food(Animal animal) {
        this.animal = animal;
    }

    @Override
    public void eat() {
        animal.eat();
    }
}

/**
 * 具体装饰器
 */
public class BarrotFood extends Food{

    public BarrotFood(Animal animal) {
        super(animal);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("可以吃胡萝卜");
    }
}

/**
 * 具体装饰器
 */
public class BambooFood extends Food{

    public BambooFood(Animal animal) {
        super(animal);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("可以吃竹子");
    }
}

public class Client {
    public static void main(String[] args) {
        Panda panda = new Panda();

        BarrotFood barrotFood = new BarrotFood(panda);
        BambooFood bambooFood = new BambooFood(barrotFood);
        bambooFood.eat();
    }
}

/**
 * 测试类
 */
public class Client {
    public static void main(String[] args) {
        Panda panda = new Panda();

        BarrotFood barrotFood = new BarrotFood(panda);
        BambooFood bambooFood = new BambooFood(barrotFood);
        bambooFood.eat();
    }
}


Kotlin

fun Panda.bamboo(decorator:()->Unit){
    eat()
    println("可以吃竹子")
    decorator()
}

fun Panda.carrot(decorator:()->Unit){
    println("可以吃胡萝卜")
    decorator()
}

fun main() {
    Panda().run { 
        bamboo { carrot {  } }
    }
}

四、建造者模式

Java

public class Pen {
    private Builder builder;

    public Pen(Builder builder) {
        this.builder = builder;
    }

    public void write() {
        System.out.println("color:" + builder.color + "  width:" + builder.width + "  round:" + builder.round);
    }

    public static class Builder {
        private String color = "white";
        private float width = 1.0f;
        private boolean round = false;

        public Builder setColor(String color) {
            this.color = color;
            return this;
        }

        public Builder setWidth(float width) {
            this.width = width;
            return this;
        }

        public Builder setRound(boolean round) {
            this.round = round;
            return this;
        }

        public Pen build() {
            return new Pen(this);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        Pen.Builder builder = new Pen.Builder();
        builder.setColor("").setRound(true).setWidth(1f).build().write();
    }
}

Kotlin

class Penk {
    var color = "white"
    var width = 1.0f
    var round = false

    fun write() {
        println("color:${color}   width:${width}   round:${round}")
    }
}

fun main() {
    val pen = Penk()    
    //使用with来实现建造者模式
    with(pen) {
        color = ""
        width = 1f
        round = true
    }
    pen.write()

    //使用apply来实现建造者模式
    pen.apply {
        color = ""
        width = 2f
        round = false
        write()
    }
}

五、适配器模式

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

分为类适配器模式

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

优点:

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

结构:

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

类适配器模式

interface Target {
    fun request1()
    fun request2()
}

//适配者类
open class Adaptee {
    fun request1() {
        println("Adaptee:request1")
    }
}

//适配器类
class AdapterClass : Adaptee(), Target {
    override fun request2() {
        println("AdapterClass:request2")
    }
}

class Client {
    fun main() {
        //类适配器
        val adapterClass = AdapterClass()
        adapterClass.apply {
            request1()
            request2()
        }
    }
}

对象适配器模式

使用委派替代继承


//适配者类
open class Adaptee {
    fun request1() {
        println("Adaptee:request1")
    }
}

//对象适配器
class AdapterObj(private var adaptee:Adaptee) :Target{
    override fun request1() {
        adaptee.request1()
    }

    override fun request2() {
        println("AdapterObj:request2")
    }
}

class Client {
    fun main() {
        //对象适配器
        val adaptee = Adaptee()
        val adapterObj = AdapterObj(adaptee)
        adapterObj.apply { 
            request1()
            request2()
        }
    }
}

优点:可以适配多个目标

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

软件架构:

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

软件框架:

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

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

设计模式:

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