Skip to content
Published at:

设计模式

分类

  • 创建型设计模式:
    • 单例模式:创建全局唯一对象
    • 工厂模式:创建类型不同但相关的对象
    • 建造者模式:创建复杂对象,可以设置不同的可选参数
    • 原型模式:创建成本比较大的对象,利用已有对象进行复制的方式进行创建,达到节省创建时间的目的
  • 结构型设计模式:
    • 代理模式:给原始类附加不相关的其他功能
    • 装饰器模式:给原始类附加相关功能(增强功能)
    • 适配器模式:解决代码兼容问题
    • 桥接模式:解决组合“爆炸”问题
    • 门面模式:接口设计(提供不同粒度的接口)
    • 组合模式:主要应用在能够表示为树形结构的数据中
    • 享元模式:解决利用问题
  • 行为型设计模式:
    • 观察者模式
    • 模板方法模式
    • 策略模式
    • 职责链模式
    • 状态模式
    • 迭代器模式
    • 访问者模式
    • 备忘录模式
    • 命令模式
    • 解释器模式
    • 中介模式

单例模式Singleton

定义:

一个类只允许创建一个对象(或实例),那么,这个类就是一个单例类,这种设计模式就称为单例设计模式

示例:

需求:实现一个 ID 的生成器的单例模式

“饿汉”式

"饿"体现在:提早就初始化好实例;不管你用不用,先把实例创建好。

java
public class IdGenerator {
    private AtomicLong id = new AtomicLong(0);
    private static final IdGenerator instance = new IdGenerator();

    private IdGenerator(){}

    public static IdGenerator getInstance() {
        return instance;
    }

    public Long getId() {
        return id.incrementAndGet();
    }
}

“懒汉”式

“懒”体现在:需要时(实际用到时)才创建实例。

java
public class IdGenerator {
    private AtomicLong id = new AtomicLong(0);
    private static IdGenerator instance;

    private IdGenerator(){}

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

    public Long getId() {
        return id.incrementAndGet();
    }
}

双重检测

并发问题:可能存在两个线程同时会创建实例;双重检测避免另一个问题:避免后面调用些函数时,使用锁的开销,不用每次执行这些代码都需要去获取互斥锁

java
public class IdGenerator {
    private AtomicLong id = new AtomicLong(0);
    private static IdGenerator instance;

    private IdGenerator(){}

    public static IdGenerator getInstance() {
        if (instance == null) {
            synchronized(IdGenerator.class) {
                if (instance == null) {
                    instance = new IdGenerator();
                }
            }
        }
        return instance;
    }

    public Long getId() {
        return id.incrementAndGet();
    }
}

静态内部类

java
public class IdGenerator {
    private AtomicLong id = new AtomicLong(0);
    private IdGenerator(){}

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

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

    public Long getId() {
        return id.incrementAndGet();
    }
}

枚举

Java的枚举值INSTANCE本质是当前 IdGenerator 类的实例,另外,枚举里面也可以写成员和函数

java
public enum IdGenerator{
    INSTANCE;

    private AtomicLong id = new AtomicLong(0);

    public long getId() {
        return id.incrementAndGet();
    }
}

C 语言如何实现?

Java 的 static 修饰的成员有一个特点:所有的实例共用一个,一个类的所有实现共用一个;换句话来说:就那就是进程唯一;那在 C 语言里面就用一个全局变量,或是 static 修饰的局部变量实现即可。这里用后者来实现:

c
#include <stdio.h>
#include <stdatomic.h>

typedef struct {
    atomic_ulong id;
} id_generator_t;

id_generator_t* id_generator_get_instance() {
    static id_generator_t id_generator = {
        .id = ATOMIC_VAR_INIT(0),
    };
    return &id_generator;
}
unsigned long id_generator_get_id(id_generator_t* id_generator) {
    atomic_fetch_add(&id_generator->id, 1);
    return atomic_load(&id_generator->id);
}

int main(int argc, char* argv[]) {
    id_generator_t* id_generator = id_generator_get_instance();

    unsigned long id = id_generator_get_id(id_generator);
    id               = id_generator_get_id(id_generator);

    printf("id: %lu\n", id);
    return 0;
}

工厂模式

分类:

  • 简单工厂模式(是工厂方法模式的一种特例)
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式Simple Factory

java
public class RuleConfigSource {
    public RuleConfig load(String ruleConfigFilePath) {
        String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
        IRuleConfigParser parser = RuleConfigParserFactory.createParser(ruleConfigFileExtension);
        if (parser == null) {
            throw new InvalidRuleConfigException("Rule config file format is not supported:" + ruleConfigFilePath)
        }

        String configText = "";
        RuleConfig ruleConfig = parser.parse(configText);
        return ruleConfig;
    }

    public String getFileExtension(String filePath) {
        // todo:
        return "json"
    }
}

public class RuleConfigParserFactory {
    public static IRuleConfigParser createParser(String configFormat) {
        IRuleConfigParser parser = null;
        if ("json".equalsIgnoreCase(configFormat)) {
            parser = new JsonRuleConfigParser();
        } else if ("xml".equalsIgnoreCase(configFormat)) {
            parser = new XmlRuleConfigParser();
        } else if ("yaml".equalsIgnoreCase(configFormat)) {
            parser = new YamlRuleConfigParser();
        } else if ("properties".equalsIgnoreCase(configFormat)) {
            parser = new PropertiesRuleConfigParser();
        }
        return parser;
    }
}

工厂方法模式Factory Method

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

java
public interface IRuleConfigParserFactory {
    IRuleConfigParser createParser();
}

public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory {
    @override
    IRuleConfigParser createParser() {
        return new JsonRuleConfigParser();
    }
}
public class XmlRuleConfigParserFactory implements IRuleConfigParserFactory {
    @override
    IRuleConfigParser createParser() {
        return new XmlRuleConfigParser();
    }
}
public class YamlRuleConfigParserFactory implements IRuleConfigParserFactory {
    @override
    IRuleConfigParser createParser() {
        return new YamlRuleConfigParser();
    }
}
public class PropertiesRuleConfigParserFactory implements IRuleConfigParserFactory {
    @override
    IRuleConfigParser createParser() {
        return new PropertiesRuleConfigParser();
    }
}

public class RuleConfigSource {
    public RuleConfig load(String ruleConfigFilePath) {
        String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
        IRuleConfigParserFactory parserFactory = null;
        if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {
            parserFactory = new JsonRuleConfigParserFactory();
        } else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) {
            parserFactory = new XmlRuleConfigParserFactory();
        } else if ("yaml".equalsIgnoreCase(ruleConfigFileExtension)) {
            parserFactory = new YamlRuleConfigParserFactory();
        } else if ("properties".equalsIgnoreCase(ruleConfigFileExtension)) {
            parserFactory = new PropertiesRuleConfigParserFactory();
        } else if (parserFactory == null) {
            throw new InvalidRuleConfigException("Rule config file format is not supported:" + ruleConfigFilePath)
        }

        IRuleConfigParser parser = parserFactory.createParser();
        String configText = "";
        RuleConfig ruleConfig = parser.parse(configText);
        return ruleConfig;
    }

    public String getFileExtension(String filePath) {
        // todo:
        return "json"
    }
}

抽象工厂模式Abstract Factory

// todo

建造者模式Builder

场景:

构造对象时,构造参数很多、还有多种组合方式,或者属性的配置项过多的场景

示例:

需求:实现一个资源池(线程池、连接池或对象池)配置类,可以配置最大总资源数量、最大空闲资源数量、最小空闲资源数量

java
public class ResourcePoolConfig {
    private String name;
    private int maxTotal;
    private int maxIdle;
    private int minIdle;

    private ResourcePoolConfig(Builder builder) {
        this.name = builder.name;
        this.maxTotal = builder.maxTotal;
        this.maxIdle = builder.maxIdle;
        this.minIdle = builder.minIdle;
    }

    public static class Builder {
        private String name;
        private int maxTotal = DEFAULT_MAX_TOTAL;
        private int maxIdle = DEFAULT_MAX_IDLE;
        private int minIdle = DEFAULT_MIN_IDLE;

        public ResourcePoolConfig setName(String name) {
            this.name = name;
            return this;
        }
        public ResourcePoolConfig setMaxTotal(int maxTotal) {
            this.maxTotal = maxTotal;
            return this;
        }
        public ResourcePoolConfig setMaxIdle(int maxIdle) {
            this.maxIdle = maxIdle;
            return this;
        }
        public ResourcePoolConfig setMinIdle(int minIdle) {
            this.minIdle = minIdle;
            return this;
        }

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

    public static void main(String []args) {
        ResourcePoolConfig config = new ResourcePoolConfig.Builder()
            .setName("dbconnectionpool")
            .setMaxTotal(16)
            .setMaxIdle(10)
            .setMinIdle(12)
            .build();
    }
}

C 语言如何实现?

c
#include <stdio.h>
#include <stdint.h>

typedef struct lv_img_s lv_img_t;
struct lv_img_s {
    uint16_t x;
    uint16_t y;
    uint16_t width;
    uint16_t height;
    char*    src;
};

typedef struct lv_img_builder_s lv_img_builder_t;
struct lv_img_builder_s {
    uint16_t x;
    uint16_t y;
    uint16_t width;
    uint16_t height;
    char*    src;
    lv_img_builder_t* (*set_x)(lv_img_builder_t* this, uint16_t x);
    lv_img_builder_t* (*set_y)(lv_img_builder_t* this, uint16_t y);
    lv_img_builder_t* (*set_width)(lv_img_builder_t* this, uint16_t width);
    lv_img_builder_t* (*set_height)(lv_img_builder_t* this, uint16_t height);
    lv_img_builder_t* (*set_src)(lv_img_builder_t* this, const char* src);
    lv_img_t* (*build)(lv_img_builder_t* this);
};

lv_img_builder_t* lv_img_builder_set_x(lv_img_builder_t* this, uint16_t x) {
    this->x = x;
    return this;
}

lv_img_builder_t* lv_img_builder_set_y(lv_img_builder_t* this, uint16_t y) {
    this->y = y;
    return this;
}

lv_img_builder_t* lv_img_builder_set_width(lv_img_builder_t* this, uint16_t width) {
    this->width = width;
    return this;
}

lv_img_builder_t* lv_img_builder_set_height(lv_img_builder_t* this, uint16_t height) {
    this->height = height;
    return this;
}

lv_img_builder_t* lv_img_builder_set_src(lv_img_builder_t* this, const char* src) {
    this->src = strdup(src);
    return this;
}

lv_img_t* lv_img_builder_build(lv_img_builder_t* this) {
    lv_img_t* img = malloc(sizeof(lv_img_t));
    img->x        = this->x;
    img->y        = this->y;
    img->height   = this->height;
    img->width    = this->height;
    img->src      = this->src;

    free(this);
    return img;
}

lv_img_builder_t* lv_img_builder_new() {
    lv_img_builder_t* builder = malloc(sizeof(lv_img_builder_t));
    builder->set_x            = lv_img_builder_set_x;
    builder->set_y            = lv_img_builder_set_y;
    builder->set_width        = lv_img_builder_set_width;
    builder->set_height       = lv_img_builder_set_height;
    builder->set_src          = lv_img_builder_set_src;
    builder->build            = lv_img_builder_build;
    return builder;
}

int main(int argc, char* argv[]) {
    lv_img_builder_t* img_builder = lv_img_builder_new();

    lv_img_t* img = img_builder->set_x(img_builder, 10)
                        ->set_y(img_builder, 10)
                        ->set_width(img_builder, 100)
                        ->set_height(img_builder, 100)
                        ->set_src(img_builder, "foo.webp")
                        ->build(img_builder);

    printf("img:x = %d\n", img->x);
    printf("img:y = %d\n", img->y);
    printf("img:width = %d\n", img->width);
    printf("img:height = %d\n", img->height);
    printf("img:src = %s\n", img->src);
    return 0;
}

原型模式

// todo

Updated at: