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