一、单例模式
1.饿汉式
类加载时就初始化,浪费内存。
它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化
- Java
public class Singleton {
private static Singleton S = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return S;
}
}
- Kotlin
object Singleton {
}
Kotlin是如何用一行代码实现单例的呢?我们来看看反编译后的java代码:
tools--Kotlin--show Kotlin Bytecode
public final class Singleton {
public static final Singleton INSTANCE;
private Singleton() {
}
static {
Singleton var0 = new Singleton();
INSTANCE = var0;
}
}
可以看到,object修饰的类实际上就是Java里的静态单例,而静态代码是随着类加载的,只会加载一次,这样就实现了饿汉式单例
2. 懒汉式
- Java
public class Singleton{
private static Singleton S;
private Singleton(){
}
public static getInstance(){
if(S==null){
S = new Singleton();
}
return S;
}
}
- Kotlin
class Singleton private constructor() {
companion object {
val S: Singleton by lazy { Singleton() }
}
}
注:by lazy { ... }的初始化默认是线程安全的,并且能保证by lazy { ... }代码块中的代码最多被调用一次,我们深入源码看一下,lazy修饰符是如何实现懒加载和线程安全的,关键方法是SynchronizedLazyImpl(initializer):
image.png
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
// final field is required to enable safe publication of constructed instance
private val lock = lock ?: this
override val value: T
get() { //此处判断_value已被初始化,则直接返回
val _v1 = _value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}
return synchronized(lock) {//增加线程同步锁,防止并发访问
val _v2 = _value
if (_v2 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST") (_v2 as T)
} else {//未初始化时,真正实现初始化的代码
val typedValue = initializer!!()
_value = typedValue
initializer = null
typedValue
}
}
}
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
private fun writeReplace(): Any = InitializedLazyImpl(value)
}
二、建造者模式
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。下面以我们常用的Dialog举例:
- Java
public class Dialog {
private String left;
private String right;
private String title;
static class Builder {
private String left;
private String right;
private String title;
Builder left(String left) {
this.left = left;
return this;
}
Builder right(String right){
this.right = right;
return this;
}
Builder title(String title){
this.title = title;
return this;
}
Dialog build(){
Dialog dialog = new Dialog();
dialog.left = this.left;
dialog.right = this.right;
dialog.title = this.title;
return dialog;
}
}
}
class DialogTest{
void test(){
Dialog dialog = new Dialog.Builder().left("left").right("right").title("titlle").build();
}
}
- Kotlin
class Dialog{
var left:String =""
var right:String=""
var title:String ="title"
}
class DialogTest{
@Test
fun test(){
val dialog = Dialog().apply {
left = "left"
right = "right"
title = "title"
}
}
}
关键方法在于apply函数,它使得代码块能够在当前对象语境下,访问其非私有属性和函数,执行完毕后返回当前对象:
/**
* Calls the specified function [block] with `this` value as its receiver and returns `this` value.
*
* For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#apply).
*/
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
三、观察者模式
- Java
观察者
public interface Observer {
void update(Object object);
}
被观察者
public abstract class Observable {
List<Observer> observers = new ArrayList<>();
public void register(Observer observer){
this.observers.add(observer);
}
public void unRegister(Observer observer){
this.observers.remove(observer);
}
public void notifyAllObservers(Object object){
for (Observer observer : observers) {
observer.update(object);
}
}
}
- Kotlin
interface TextChangedListener {
fun onTextChanged(newText: String)
}
class TextView {
var listener: TextChangedListener? = null
var text: String by Delegates.observable("") { prop, old, new ->
listener?.onTextChanged(new)
}
}
为了弄清楚如何实现的,我们查看下Delegates.observable的源码:
/**
* Returns a property delegate for a read/write property that calls a specified callback function when changed.
* @param initialValue the initial value of the property.
* @param onChange the callback which is called after the change of the property is made. The value of the property
* has already been changed when this callback is invoked.
*
* @sample samples.properties.Delegates.observableDelegate
*/
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
ReadWriteProperty<Any?, T> =
object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
}
是不是还没有看懂,我们只需要关注ObervableProperty这个类就行了,这里值的改变实际上代理给了ObervableProperty
/**
* Implements the core logic of a property delegate for a read/write property that calls callback functions when changed.
* @param initialValue the initial value of the property.
*/
public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
private var value = initialValue
/**
* The callback which is called before a change to the property value is attempted.
* The value of the property hasn't been changed yet, when this callback is invoked.
* If the callback returns `true` the value of the property is being set to the new value,
* and if the callback returns `false` the new value is discarded and the property remains its old value.
*/
protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true
/**
* The callback which is called after the change of the property is made. The value of the property
* has already been changed when this callback is invoked.
*/
protected open fun afterChange(property: KProperty<*>, oldValue: T, newValue: T): Unit {}
public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value
}
public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
val oldValue = this.value
if (!beforeChange(property, oldValue, value)) {
return
}
this.value = value
afterChange(property, oldValue, value)
}
}
ReadWriteProperty是一个什么东西呢?它在代理模式中用得非常多:
public interface ReadWriteProperty<in R, T> {
/**
* Returns the value of the property for the given object.
* @param thisRef the object for which the value is requested.
* @param property the metadata for the property.
* @return the property value.
*/
public operator fun getValue(thisRef: R, property: KProperty<*>): T
/**
* Sets the value of the property for the given object.
* @param thisRef the object for which the value is requested.
* @param property the metadata for the property.
* @param value the value to set.
*/
public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}
当一个值被ReadWritPropery代理时,调用或者赋值都会相应地回调getValue和setValue方法
我们继续回ObservableProperty,到从命名就可以看出来,其是一个被观察者,当它的值发生改变时,会回调afterChange方法,最终会传递给我们自定义的onChange方法中,实现值的变化监听,这样就实现了最简单的观察者模式
四、代理模式
在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。下面举一个经纪人代理明星的例子:
interface People {
fun speak()
}
class Broker :People{
override fun speak() {
print("hello")
}
}
class Star(private val broker: Broker) :People by broker
class Test{
@Test
fun test(){
val broker = Broker()
val star = Star(broker)
star.speak()
}
}
在Koltin中实现代理模式非常简单,只需要试用by关键字就行了,上面的Star就是通过 传入的broker实现的代理,我们看到它自身是没有实现People类的抽象方法的,最终在test()中调用的实际上是其代理对象broker的speak,在Kotlin中by关键字主要有如下几点作用:
- 类的代理 class
- 属性延迟加载 lazy
- 监听属性变化 Delegates.observable ( 扩展 Delegates.vetoable )
- 自定义监听属性变化 ReadWriteProperty
我们再举个栗子,看看其如何实现属性的代理,和上面讲过的观察者模式有些类似
class Delegate {
// 运算符重载
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String {
return "$thisRef, thank you for delegating '${prop.name}' to me!"
}
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: String) {
println("$value has been assigned to ${prop.name} in $thisRef")
}
}
class Example {
var d: String by Delegate()
@Test
fun test(){
d = "d value"
println("$d")
}
}
运行结果是这样的:
image.png
从结果看,String类型的d的取值和赋值已经交给了Delegate类去实现,想不想知道如何实现的?我们来反编译下看看源码吧
public final class Delegate {
@NotNull
public final String getValue(@Nullable Object thisRef, @NotNull KProperty prop) {
Intrinsics.checkParameterIsNotNull(prop, "prop");
return thisRef + ", thank you for delegating '" + prop.getName() + "' to me!";
}
public final void setValue(@Nullable Object thisRef, @NotNull KProperty prop, @NotNull String value) {
Intrinsics.checkParameterIsNotNull(prop, "prop");
Intrinsics.checkParameterIsNotNull(value, "value");
String var4 = value + " has been assigned to " + prop.getName() + " in " + thisRef;
boolean var5 = false;
System.out.println(var4);
}
}
public final class Example {
// $FF: synthetic field
static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty1(new MutablePropertyReference1Impl(Reflection.getOrCreateKotlinClass(Example.class), "d", "getD()Ljava/lang/String;"))};
@NotNull
private final Delegate d$delegate = new Delegate();
@NotNull
public final String getD() {
return this.d$delegate.getValue(this, $$delegatedProperties[0]);
}
public final void setD(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.d$delegate.setValue(this, $$delegatedProperties[0], var1);
}
@Test
public final void test() {
this.setD("d value");
String var1 = String.valueOf(this.getD());
boolean var2 = false;
System.out.println(var1);
}
}
可以看到,Example中给d取值和赋值实际上调用的是getD和setD方法,而且最终转而被Delegate对象代理,调用的是它的getValue和setValue方法,这个其实就是代理模式中by关键字的作用
网友评论