软件设计模式

1. 设计模式定义

1.1 什么是设计模式

在 GoF(Gang of Four)的书籍《设计模式-可复用面向对象软件的基础》中是这样定义设计模式的:“每一个模式描述了一个在我们周围不断重复发生的问题以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。

一般而言,设计模式有四个基本要素:

  1. 模式名称(pattern name):一个助记名,它用一两个词来描述模式的问题、解决方案和效果。
  2. 问题(problem):描述了应该在何时使用模式。
  3. 解决方案(solution):描述了设计的组成成分,它们之间的相关关系以及各自的职责和协作方案。
  4. 效果(consequences):描述了模式应用的效果以及使用模式应该权衡的问题。

1.2 设计原则与设计模式

设计原则和设计模式的关系:

  • 设计原则是指导思想,往往是高度概括性和原则性的;设计模式是实现方式,并且往往并非一种实现方式。
  • 设计原则由设计模式共同遵守,一种设计模式往往采用多种设计原则。

1.3 设计原则分类

1.3.1 根据目的来分

  • 创建型模式:抽象了对象的实例化过程,将对象的创建和使用分离。
    • 单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式
  • 结构型模式:处理类或对象的组合,实现新功能。
    • 适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式
  • 行为型模式: 算法和对象间职责的分配,关注对象间的联系方式。
    • 责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

2. 创建型模式

2.1 单例模式(Singleton)

2.1.1 定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式主要解决两个问题:

  • 保证一个类仅有一个实例:
    • 作用:(1)防止重复创建导致的资源浪费(2)防止多个实例导致的数据同步问题
    • 使用:控制某些共享资源 (例如数据库或文件) 的访问权限等
    • 实现:private 修饰构造函数,在类中创建对象
  • 为该实例提供一个全局访问节点:
    • 作用:防止实例数据被覆盖
    • 实现:提供全局访问方法

2.1.2 实现

单例模式结构

饿汉式-线程安全

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

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

懒汉式-线程不安全

public class Singleton {

    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

懒汉式-线程安全

public static synchronized Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

懒汉式-双重校验锁-线程安全

public class Singleton {

    private static volatile Singleton instance; // volatile 防止JVM对指令进行重排

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) { // 防止两个线程都在第一个if判断instance为null,先后进入锁创建实例
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

使用内部类的好处是,静态内部类不会在单例加载时就加载,而是在调用 getInstance() 方法时才进行加载,而且由 JVM 提供了对线程安全的支持。

public class Singleton {

    private Singleton() {
    }

    private static class SingletonHolder {
        private static Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

枚举实现

单例模式的最佳实现,能保证只有一个实例且线程安全,并且在面对复杂的序列化或者反射攻击的时候,能够防止实例化多次,唯一缺点是无法适用继承场景。

public enum Singleton {
    instance;
}

2.2 工厂方法模式(Factory Method)

2.2.1 定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。

2.2.2 实现

img

2.3 抽象工厂模式(Abstract Factory)

2.3.1 定义

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

2.3.2 实现

img

2.4 建造者模式(Builder)

2.4.1 定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

2.4.2 实现

img

以下是一个简易的 StringBuilder 实现,参考了 JDK 1.8 源码。

abstract class AbstractStringBuilder {
    char[] value;
    int count;
    
    AbstractStringBuilder() {
    }

    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
    
    public AbstractStringBuilder append(char c) {
        ensureCapacityInternal(count + 1);
        value[count++] = c;
        return this;
    }
    
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
    
    private int expandCapacity(int minCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) {
            if (Integer.MAX_VALUE - minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? minCapacity : MAX_ARRAY_SIZE;
        }
		return newCapacity;
    }
    
    public abstract String toString();
}
public final class StringBuilder extends AbstractStringBuilder {
    public StringBuilder() {
        super(16);
    }
    
    @Override
    public StringBuilder append(char c) {
        super.append(c);
        return this;
    }
    
	@Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }
}

3. 结构性模式

3.1 适配器模式(Adapter)

3.1.1 定义

将一个类的接口转换成客户希望的另外一个接口。

3.1.2 实现

img

3.2 桥接模式(Bridge)

3.2.1 定义

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

3.2.2 实现

桥接设计模式

3.3 装饰器模式(Decorator)

3.3.1 定义

动态地给一个对象添加一些额外的职责。

3.3.2 实现

装饰设计模式的结构

3.4 代理模式(Proxy)

3.4.1 定义

为其他对象提供一种代理以控制对这个对象的访问。

3.4.2 实现

代理设计模式的结构

4. 行为型模式

4.1 观察者模式(Observer)

4.1.1 定义

定义对象间的一种一对多的依赖关系 ,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

4.1.2 实现

观察者设计模式的结构

4.2 策略模式(Strategy)

4.2.1 定义

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

4.2.2 实现

img

4.3 模板方法模式(Template Method)

4.3.1 定义

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

4.3.2 实现

img

4.4 责任链模式(Chain of Responsibility)

4.4.1 定义

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

4.4.2 实现

责任链设计模式的结构

4.5 迭代器模式(Iterator)

4.5.1 定义

提供一种方法顺序访问一个聚合对象中各个元素 , 而又不需暴露该对象的内部表示。

4.5.2 实现

迭代器设计模式的结构

4.6 状态模式(State)

4.6.1 定义

允许一个对象在其内部状态改变时改变它的行为。

4.6.2 实现

状态模式和策略模式的区别:状态模式中特定状态知道其它状态的存在,且可以切换到其它状态;而策略模式中,一个策略并不知晓其它策略的存在。

状态设计模式的结构

参考资料

  1. 《设计模式:可复用面向对象软件的基础》学习笔记
  2. 设计模式知识体系详解
  3. 深入设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值