一、前言
二、单例模式
饿汉模式
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)是整个或部分系统的可重用设计,表现为一组抽象架构及构件实例间交互的方法
框架是一种特殊的软件,它并不能提供完整无缺的解决方案,而是为你构建解决方案提供良好的基础
设计模式:
在软件工程中,设计模式是对软件设计中普遍存在的各种问题,所提出的解决方案。设计模式是解决局部问题的方法