image

常见23种设计模式

  • WORDS 35481

创建型模式

工厂模式(Factory Method)

工厂方法模式旨在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。 适用场景:

  • 无法预知对象类别和其依赖关系时
  • 希望软件库或框架的内部组件可扩展
  • 复用现有对象来节省资源
// GUI Button的跨平台实现
interface Button {  
    void render();  
    void onClick();  
}  

// Windows 平台实现
class WindowsButton implements Button {  
    @Override  
    public void render() {}  
    @Override  
    public void onClick() {}  
}  

// Html实现
class HtmlButton implements Button {  
    @Override  
    public void render() {}  
    @Override  
    public void onClick() {}  
}

在使用时,通过 new 不同的子类实现工厂模式

public class Main {  
    public static void main(String[] args) {  
        Button button = new WindowsButton();  
    }  
}

golang 中,由于不存在继承关系,所有只能使用简单工厂模式,可以将返回接口类型的构造函数都看做简单工厂。

func main() {  
    btn := NewWindowsButton()  
}  
  
type Button interface {  
    render()  
    onClick()  
}  
  
type WindowsButton struct{}  
// 可以看做一个简单工厂
func NewWindowsButton() Button {  
    return &WindowsButton{}  
}  
  
func (self *WindowsButton) render() {}  
  
func (self *WindowsButton) onClick() {}  
  
type HtmlButton struct{}  
// 可以看做一个简单工厂
func NewHtmlButton() Button {  
    return &HtmlButton{}  
}  
  
func (self *HtmlButton) render() {}  
  
func (self *HtmlButton) onClick() #### [](https://refactoringguru.cn/design-patterns/proxy/go/example#example-0--nginx-go)**nginx.go:** 代理{}

抽象工厂模式(Abstract Factory)

抽象工厂借助于工厂方法,用于创建一系列相关的对象,而不需指定其具体实现类。 适用场景:

  • 在无法提前获取相关信息的前提下需要与多个不同系列的产品交互
  • 将一组功能不明确的基于抽象方法的类抽取为抽象工厂
// 一系列产品
interface Component {  
    void render();  
}  
interface Button extends Component {  
    void onClick();  
}  
interface Label extends Component {  
    void setText();  
}  

// 跨平台GUI的抽象工厂
interface GUIFactory {  
	// 创建产品的抽象方法
    Button createButton();  
    Label createLabel();  
}  
// 每个平台的工厂实现自己的产品创建逻辑
class WindowsFactory implements GUIFactory {  
    @Override  
    public Button createButton() {  
        return new WindowsButton();  
    }  
  
    @Override  
    public Label createLabel() {  
        return new WindowsLabel();  
    }  
}  
  
class WindowsButton implements Button {  
    @Override  
    public void onClick() {}  
  
    @Override  
    public void render() {}  
}  
  
class WindowsLabel implements Label {  
    @Override  
    public void setText() {}  
  
    @Override  
    public void render() {}  
}  
  
class HtmlFactory implements GUIFactory {  
    @Override  
    public Button createButton() {  
        return new HtmlButton();  
    }  
  
    @Override  
    public Label createLabel() {  
        return new HtmlLabel();  
    }  
}  
  
class HtmlButton implements Button {  
    @Override  
    public void onClick() {}  
  
    @Override  
    public void render() {}  
}  
  
class HtmlLabel implements Label {  
    @Override  
    public void setText() {}  
  
    @Override  
    public void render() {}  
}

在使用时,只需要指定不同的 factory 实现,而后通过此工厂类创建产品。

public class Main {  
    public static void main(String[] args) {  
        GUIFactory factory;  
        if ("windows".equals(args[0])) {  
            factory = new WindowsFactory();  
        } else {  
            factory = new HtmlFactory();  
        }  
        Button button = factory.createButton();  
        Label label = factory.createLabel();  
    }  
}

golang 中也可以实现抽象工厂模式

func main() {  
    var factory GUIFactory  
    if os.Args[0] == "windows" {  
       factory = &WindowsFactory{}  
    } else {  
       factory = &HtmlFactory{}  
    }  
    btn := factory.createButton()  
    label := factory.createLabel()  
}  
  
type Component interface {  
    render()  
}  
// 使用组合实现代码抽取
type Button interface {  
    Component  
    onClick()  
}  
type Label interface {  
    Component  
    setText(text string)  
}  
  
type GUIFactory interface {  
    createButton() Button  
    createLabel() Label  
}  
  
type WindowsFactory struct{}  
func (self *WindowsFactory) createButton() Button {  
    return &WindowsButton{}  
}  
func (self *WindowsFactory) createLabel() Label {  
    return &WindowsLabel{}  
}  
  
type HtmlFactory struct {}  
func (self *HtmlFactory) createButton() Button {  
    return &HtmlButton{}  
}  
func (self *HtmlFactory) createLabel() Label {  
    return &HtmlLabel{}  
}  
  
type WindowsButton struct{}  
func (self *WindowsButton) render() {}  
func (self *WindowsButton) onClick() {}  
  
type WindowsLabel struct{}  
func (slef *WindowsLabel) render() {}  
func (slef *WindowsLabel) setText(text string) {}  
  
type HtmlButton struct{}  
func (self *HtmlButton) render() {}  
func (self *HtmlButton) onClick() {}  
  
type HtmlLabel struct{}  
func (self *HtmlLabel) render() {}  
func (self *HtmlLabel) setText(text string) {}

创建者模式(Builder)

生成器模式旨在简化创建负责对象的步骤,可以使用相同的代码创建不同类型和形式的对象。 适用场景:

  • 有大量重复构造函数可以使用 Builder 简化
  • 希望可以重用代码创建不同形式的产品
  • 使用生成器创建组合树或其它复杂对象
// 定义构造器接口
interface Builder<T> {  
    T build();  
}  
  
class Student {  
    private Integer id;  
    private String name;  
    private Integer age;  
    private String city;  
  
    public Student() {}  
    public Student(Integer id, String name, Integer age, String city) {  
        this.id = id;  
        this.name = name;  
        this.age = age;  
        this.city = city;  
    }
    // 静态的builder方法 返回构造器  
    static public StudentBuilder builder() {  
        return new StudentBuilder();  
    }  
}  
  
class StudentBuilder implements Builder<Student> {  
    private Integer id;  
    private String name;  
    private Integer age;  
    private String city;  
    // 返回this实现链式调用
    public StudentBuilder setId(Integer id) {  
        this.id = id;  
        return this;  
    }  
    public StudentBuilder setName(String name) {  
        this.name = name;  
        return this;  
    }  
    public StudentBuilder setAge(Integer age) {  
        this.age = age;  
        return this;  
    }  
    public StudentBuilder setCity(String city) {  
        this.city = city;  
        return this;  
    }  
    @Override  
    public Student build() {  
        return new Student(this.id, this.name, this.age, this.city);  
    }  
}

使用构造器创建对象

public class Main {  
    public static void main(String[] args) {
	    // 通过链式调用创建
        Student student = Student.builder()  
                .setName("学生")  
                .setAge(18)  
                .setCity("中国")  
                .build();  
    }  
}

golang 中也一样

func main() {  
    student := NewStudentBuilder().  
       setName("学生").  
       setAge(18).  
       setCity("中国").  
       build()  
    fmt.Println(student.Name)  
}  
  
type Student struct {  
    Id   uint  
    Name string  
    Age  uint  
    City string  
}  
type StudentBuilder struct {  
    id   uint  
    name string  
    age  uint  
    city string  
}
// 创建构造器
func NewStudentBuilder() *StudentBuilder {  
    return &StudentBuilder{}  
}  
func (self *StudentBuilder) setId(id uint) *StudentBuilder {  
    self.id = id  
    return self  
}  
func (self *StudentBuilder) setName(name string) *StudentBuilder {  
    self.name = name  
    return self  
}  
func (self *StudentBuilder) setAge(age uint) *StudentBuilder {  
    self.age = age  
    return self  
}  
func (self *StudentBuilder) setCity(city string) *StudentBuilder {  
    self.city = city  
    return self  
}  
func (self *StudentBuilder) build() *Student {  
    return &Student{  
       Id:   self.id,  
       Name: self.name,  
       Age:  self.age,  
       City: self.city,  
    }  
}

原型模式(Prototype)

原型模式用于复制现有的对象,并无需依赖其所属的类。 适用场景:

  • 如果需要复制对象,同时需要代码独立于其所属的具体类
interface Component {  
    void render();  
}
// 抽象图形类 提供抽象的clone方法
abstract class AbstractShape implements Component, Cloneable {  
    public int x;  
    public int y;  
    public AbstractShape(){}  
  
    public AbstractShape(AbstractShape target) {  
        this.x = target.x;  
        this.y = target.y;  
    }  
    public abstract AbstractShape clone();  
}
// 具体的子类实现
class Circle extends AbstractShape {  
    public int radius;  
    public Circle() {}  
    public Circle(Circle target) {  
        super(target);  
        this.radius = target.radius;  
    }  
    @Override  
    public Circle clone() {  
        return new Circle(this);  
    }  
    @Override  
    public void render() {}  
}  
class Square extends AbstractShape {  
    public int width;  
    public int height;  
    public Square() {}  
    public Square(Square target) {  
        super(target);  
        this.width = target.width;  
        this.height = target.height;  
    }  
    @Override  
    public Square clone() {  
        return new Square(this);  
    }  
    @Override  
    public void render() {}  
}

使用 clone() 方法复制对象

public class Main {  
    public static void main(String[] args) {  
        Circle circle = new Circle();  
        Circle circleCopy = circle.clone();  
    }  
}

golang 中可以直接创建 cloneable 接口用于克隆对象

func main() {  
    student := &Student{}  
    studentCopy := student.Clone()  
}

// 提供克隆方法的接口
type Cloneable[T any] interface {  
    Clone() T  
}  
type Student struct {  
    Id   uint  
    Name string  
    Age  uint  
    City string  
}  
// clone方法实现
func (self *Student) Clone() *Student {  
	// 两种方法深拷贝
    // 手动赋值 简单对象可以使用  
    return &Student{  
       Id:   self.Id,  
       Name: self.Name,  
       Age:  self.Age,  
       City: self.City,  
    }  
    // 使用序列化和反序列化实现深拷贝  
    newStudent := &Student{}  
    jsonValue, _ := json.Marshal(self)  
    _ = json.Unmarshal(jsonValue, newStudent)  
    return newStudent  
}

单例模式(Singleton)

单例模式用于保证一个类只有一个实例,并提供一个可以访问该实例的全局节点,典型应用例如 SpringIOC 容器。单例模式可以和工厂方法模式配置使用,当调用工厂方法时,实例不存在则创建,存在则返回已有实例。 适用场景:

  • 要求某个类在应用中只允许存在一个可用的实例
  • 严格控制全局变量
// 通过工厂类实现单例模式
class ExecutorFactory {  
    private static ExecutorService executorService = null;  
    // 在单线程下,直接判断是否为null 返回初始化返回即可
    public static ExecutorService getExecutorService() {  
        if (executorService == null) {  
            executorService = Executors.newFixedThreadPool(8);  
        }  
        return executorService;  
    }  
}

// 多线程下使用原子操作确保线程安全
class ExecutorFactory {  
    private static final AtomicReference<ExecutorService> atomicExecutorService = new AtomicReference<>();  
    public static ExecutorService getExecutorService() {  
        if (atomicExecutorService.get() == null) {  
            atomicExecutorService.set(Executors.newFixedThreadPool(8));  
        }  
        return atomicExecutorService.get();  
    }  
}

在代码中使用

public class Main {  
    public static void main(String[] args) {  
        ExecutorFactory.getExecutorService().submit(() -> {  
            System.out.println("hello world");  
        });  
        ExecutorService service1 = ExecutorFactory.getExecutorService();  
        ExecutorService service2 = ExecutorFactory.getExecutorService();  
        // true
        System.out.println(service1.equals(service2));  
    }  
}

golang 中由于包变量和包函数的存在,单例模式会更有用

var builder *strings.Builder  
var nameOnce sync.Once  

// 使用once简化多线程安全操作
func GetBuilder() *strings.Builder {  
    nameOnce.Do(func() {  
       builder = &strings.Builder{}  
    })  
    return builder  
}

使用

func main() {
	// 获取到的始终是同一个builder对象
    builder := GetBuilder()  
    fmt.Println(builder.String())  
    builder.WriteString("hello world")  
    builder2 := GetBuilder()  
    fmt.Println(builder2.String())  
}

结构性模式

适配器模式(Adapter)

适配器模式用于将一种接口适配另一种接口,使不兼容的接口能够相互合作。 适用场景:

  • 当某个类的接口与其它代码不兼容时
// 数据分析服务  
interface AnalyzeService {  
    /**  
     * 分析交易数据  
     * @param jsonValue 传入json数据  
     */  
    void analyzeTradeData(String jsonValue);  
}  
  
class HadoopAnalyzeService implements AnalyzeService {  
    @Override  
    public void analyzeTradeData(String jsonValue) {}  
}  

// 提供适配器,用于适配xml数据的分析
class HadoopAnalyzeServiceAdapter extends HadoopAnalyzeService {  
  
    private final AnalyzeService analyzeService;  
  
    public HadoopAnalyzeServiceAdapter(AnalyzeService hadoopAnalyzeService) {  
        this.analyzeService = hadoopAnalyzeService;  
    }  
  
    @Override  
    public void analyzeTradeData(String jsonValue) {  
        analyzeService.analyzeTradeData(jsonValue);  
    }  
  
    // 分析xml数据  
    public void analyzeTradeDataByXml(String xmlValue) {  
        // 将xml数据转为json数据  
        // 然后再分析  
        String jsonValue = xmlValue;  
        analyzeService.analyzeTradeData(jsonValue);  
    }  
}

在使用时,需要先创建服务,再创建适配器使用

public class Main {  
    public static void main(String[] args) {  
	    // 获取待分析的数据
        String tradeData = "...";  
        // 创建分析服务
        AnalyzeService analyzeService = new HadoopAnalyzeService();  
        // 创建适配器
        HadoopAnalyzeServiceAdapter analyzeAdapter = new HadoopAnalyzeServiceAdapter(analyzeService);  
        // 使用适配的接口分析原生接口不支持的数据
        analyzeAdapter.analyzeTradeDataByXml(tradeData);  
    }  
}

golang 中也是一样的

type AnalyzeService interface {  
    analyzeTradeData(jsonValue string)  
}  
  
type HadoopAnalyzeService struct{}  
  
func (self *HadoopAnalyzeService) analyzeTradeData(jsonValue string) {}  
  
type HadoopAnalyzeServiceAdapter struct {  
    analyzeService AnalyzeService  
}  
  
func NewHadoopAnalyzeServiceAdapter(analyzeService AnalyzeService) *HadoopAnalyzeServiceAdapter {  
    return &HadoopAnalyzeServiceAdapter{  
       analyzeService: analyzeService,  
    }  
}  
  
func (self *HadoopAnalyzeServiceAdapter) analyzeTradeData(jsonValue string) {  
    self.analyzeService.analyzeTradeData(jsonValue)  
}  
  
func (self *HadoopAnalyzeServiceAdapter) analyzeTradeDataByXML(xmlValue string) {  
    // 将xml数据转为json数据
    xmlData := make(map[string]any)  
    _ = xml.Unmarshal([]byte(xmlValue), &xmlData)  
    jsonValue, _ := json.Marshal(xmlData)  
    self.analyzeTradeData(string(jsonValue))  
}

使用

func main() {  
    xmlValue := "..."  
    analyze := &HadoopAnalyzeService{}  
    analyzeAdapter := NewHadoopAnalyzeServiceAdapter(analyze)  
    analyzeAdapter.analyzeTradeDataByXML(xmlValue)  
}

桥接模式(Bridge)

桥接模式可以分离一个类的抽象和实现部分,变成两个独立的层次结构,在开发时可以分别使用。 适用场景:

  • 拆分或重组具有多个功能的复杂类
  • 运行时切换不同的实现
// 设备接口
interface Device {  
    boolean isEnable();  
    void enable();  
    void disable();  
    int getVolume();  
    void setVolume(int volume);  
}  
  
class Radio implements Device {  
    @Override  
    public boolean isEnable() {  
        return false;  
    }  
    @Override  
    public void enable() {}  
    @Override  
    public void disable() {}  
    @Override  
    public int getVolume() {  
        return 0;  
    }  
    @Override  
    public void setVolume(int volume) {}  
}  
  
class Tv implements Device {  
    @Override  
    public boolean isEnable() {  
        return false;  
    }  
    @Override  
    public void enable() {}  
    @Override  
    public void disable() {}  
    @Override  
    public int getVolume() {  
        return 0;  
    }  
    @Override  
    public void setVolume(int volume) {}  
}  
  
// 控制器接口  
interface Controller {  
    void power();  
    void volumeUp();  
    void volumeDown();  
}  
  
// 基础控制器  
class BaseController implements Controller {  
    protected final Device device;  
    public BaseController(Device device) {  
        this.device = device;  
    }  
    @Override  
    public void power() {  
        if (device.isEnable()) {  
            device.disable();  
        } else {  
            device.enable();  
        }  
    }  
    @Override  
    public void volumeUp() {  
        int currentVolume = device.getVolume();  
        if (currentVolume < 100) {  
            int upVolume = Math.min(10, 100 - currentVolume);  
            device.setVolume(currentVolume + upVolume);  
        }  
    }  
    @Override  
    public void volumeDown() {  
        int currentVolume = device.getVolume();  
        if (currentVolume > 0) {  
            int downVolume = Math.min(10, currentVolume);  
            device.setVolume(currentVolume - downVolume);  
        }  
    }  
}  
  
// 高级控制器  
class AdvancedController extends BaseController {  
    public AdvancedController(Device device) {  
        super(device);  
    }  
    // 将设备静音  
    public void mute() {  
        if (device.getVolume() > 0) {  
            device.setVolume(0);  
        }  
    }  
}

在使用时通过不同的控制器去桥接控制设备

public class Main {  
    public static void main(String[] args) {  
        Device radio = new Radio();  
        Device tv = new Tv();  
        BaseController baseController = new BaseController(radio);  
        AdvancedController advancedController = new AdvancedController(tv);  
        baseController.power();  
        advancedController.mute();  
    }  
}

go 中以不同平台下不同品牌的打印机适配为例

// Printer 打印机  
type Printer interface {  
    PrintFile()  
}  

type Computer interface {  
    Print()  
    SetPrinter(printer Printer)  
}  
// Windows平台
type Windows struct {  
    printer Printer  
}  
func (self *Windows) Print() {  
    self.printer.PrintFile()  
}  
func (self *Windows) SetPrinter(printer Printer) {  
    self.printer = printer  
}  
// Linux平台  
type Linux struct {  
    printer Printer  
}  
func (self *Linux) Print() {  
    self.printer.PrintFile()  
}  
func (self *Linux) SetPrinter(printer Printer) {  
    self.printer = printer  
}  
  
// HpPrinter 惠普打印机  
type HpPrinter struct{}  
func (self *HpPrinter) PrintFile() {}  
  
// AsusPrinter 华硕打印机  
type AsusPrinter struct{}  
func (self *AsusPrinter) PrintFile() {}

通过桥接让平台和打印设备之间解耦

func main() {  
    hpPrinter := &HpPrinter{}  
    asusPrinter := &AsusPrinter{}  

    windows := &Windows{}  
    windows.SetPrinter(hpPrinter)  
    windows.Print()  
    windows.SetPrinter(asusPrinter)  
    windows.Print()  
  
    linux := &Linux{}  
    linux.SetPrinter(hpPrinter)  
    linux.Print()  
    linux.SetPrinter(asusPrinter)  
    linux.Print()  
}

组合模式(Composite)

组合模式可以将对象像树状结构一样组合起来,同时可以通过独立对象来使用。 适用场景:

  • 需要实现树状对象结构
  • 希望代码可以复用处理简单和负责元素
func main() {
	// 组件可以单独实现
    textCompress := NewTextCompress()  
    aesEncryptor := NewAESEncryptor([]byte("hello"))  
    textCompress.Encode([]byte("hello"))  
    aesEncryptor.Encrypt([]byte("hello"))  
    // 也可以使用组合在一起使用
    tools := NewCommonTools(textCompress, aesEncryptor)  
    tools.Encode([]byte(""))  
    tools.Encrypt([]byte(""))  
}  

// 单独的压缩组件
type Compress interface {  
    Encode(data []byte) []byte  
    Decode(data []byte) []byte  
}  
type TextCompress struct{}  
func NewTextCompress() Compress {  
    return &TextCompress{}  
}  
func (self *TextCompress) Encode(data []byte) []byte {  
    return data  
}  
func (self *TextCompress) Decode(data []byte) []byte {  
    return data  
}  

// 加密组件
type Encryptor interface {  
    Encrypt(data []byte) []byte  
    Decrypt(data []byte) []byte  
}  
type AESEncryptor struct {  
    aesCipher cipher.Block  
}  
func NewAESEncryptor(key []byte) Encryptor {  
    newCipher, _ := aes.NewCipher(key)  
    return &AESEncryptor{aesCipher: newCipher}  
}  
func (self *AESEncryptor) Encrypt(data []byte) []byte {  
    // ...  
}  
func (self *AESEncryptor) Decrypt(data []byte) []byte {  
    // ...  
}  

// 使用组合组装多个组件
type CommonTools struct {  
    Compress  
    Encryptor}  
func NewCommonTools(compress Compress, encryptor Encryptor) *CommonTools {  
    return &CommonTools{  
       Compress:  compress,  
       Encryptor: encryptor,  
    }  
}

装饰模式(Decorator)

装饰模式通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 适用场景:

  • 在不修改代码的情况下,在运行时为对象新增额外的行为
  • 在不能使用继承来扩展对象行为的情况下使用装饰模式
interface Consumer {  
    void writeMessage(String message);  
}  
  
/**  
 * 通知接口  
 */  
interface Notifier {  
    void addConsumer(Consumer consumer);  
    void send(String message);  
}  
  
class SimpleNotifier implements Notifier {  
    private final Set<Consumer> consumers = new HashSet<>();  
  
    @Override  
    public void addConsumer(Consumer consumer) {  
        consumers.add(consumer);  
    }  
  
    @Override  
    public void send(String message) {  
        consumers.forEach(consumer -> consumer.writeMessage(message));  
    }  
}  
  
/**  
 * 通知接口的装饰器  
 */  
abstract class NotifierDecorator implements Notifier {  
    private final Notifier notifier;  
  
    NotifierDecorator(Notifier notifier) {  
        this.notifier = notifier;  
    }  
  
    @Override  
    public void addConsumer(Consumer consumer) {  
        this.notifier.addConsumer(consumer);  
    }  
  
    @Override  
    public void send(String message) {  
        this.notifier.send(message);  
    }  
}  
  
/**  
 * 通过继承装饰器抽象类,在保留通知接口功能的同时扩展了向微信客户端发送消息的功能  
 */  
class WechatNotifier extends NotifierDecorator {  
  
    private final Set<String> wechatClients = new HashSet<>();  
  
    public WechatNotifier(Notifier notifier) {  
        super(notifier);  
    }  
    public void addWechatClient(String wechatClientPath) {  
        this.wechatClients.add(wechatClientPath);  
    }  
    public void setWechatMessage(String message) {  
        this.wechatClients.forEach(wechatClient -> {  
            // 遍历客户端发送消息  
        });  
    }  
}

在代码中使用

public class Main {  
    public static void main(String[] args) {  
        WechatNotifier wechatNotifier = new WechatNotifier(new SimpleNotifier());  
        wechatNotifier.send("hello world");  
        wechatNotifier.setWechatMessage("hello world");  
    }  
}

外观模式(Facade)

外观模式可以为程度库、框架和其他油复杂类提供一个便于使用的简单接口。 适用场景:

  • 需要一个指向复杂子系统的简单接口
  • 需要将子系统组织为多层架构

享元模式(Flyweight)

享元模式抛弃了在每个对象中保存数据的方式,通过共享在多个对象中所共同拥有的相同状态,从而达到节省内存和减少对象数据的目的。 适用场景:

  • 仅在必须支持大量对象且内存容量不足时使用享元模式
// 服装享元接口  
interface Dress {  
    String getColor();  
}  
  
class ManDress implements Dress {  
    private final String color;  
  
    public ManDress(String color) {  
        this.color = color;  
    }  
    @Override  
    public String getColor() {  
        return this.color;  
    }  
}  
  
class WomanDress implements Dress {  
    private final String color;  
  
    public WomanDress(String color) {  
        this.color = color;  
    }  
    @Override  
    public String getColor() {  
        return this.color;  
    }  
}  
  
// 班级享元  
class ClassType {  
    public final String classNo;  
    public final String className;  
    public final int count;  
  
    public ClassType(String classNo, String className, int count) {  
        this.classNo = classNo;  
        this.className = className;  
        this.count = count;  
    }  
}  
  
// 学生对象 包含了两个享元对象  
class Student {  
    public final String studentNo;  
    public final String studentName;  
    public final int age;  
    public final Dress dress;  
    public final ClassType classType;  
  
    public Student(String studentNo, String studentName, int age, Dress dress, ClassType classType) {  
        this.studentNo = studentNo;  
        this.studentName = studentName;  
        this.age = age;  
        this.dress = dress;  
        this.classType = classType;  
    }  
}

创建大量学生对象时,先创建享元,所有学生对象使用相同的数据

public class Main {  
    public static void main(String[] args) {  
        Dress manDress = new ManDress("blue");  
        Dress womanDress = new WomanDress("red");  
        ClassType classType = new ClassType("301", "三班", 24);  
        List<Student> studentList = new ArrayList<>();  
        for (int i = 0; i < 24; i++) {  
            Student student = new Student("20000" + i, String.valueOf(i), 16, i % 2 == 0 ? womanDress : manDress, classType);  
            studentList.add(student);  
        }  
    }  
}

代理模式(Proxy)

代理模式用于控制对原对象的访问,可以延迟将请求提交给对象或者在实际处理的前后进行其它操作。(SpringAOP 就是基于代理的) 使用场景:

  • 延迟初始化
  • 访问控制
  • 本地执行远程服务
  • 日志请求记录
  • 缓存结果请求
  • 智能引用
// 用户服务接口
interface UserService {  
    String login(String username, String password, String code);  
}  
  
class UserServiceImpl implements UserService {  
    @Override  
    public String login(String username, String password, String code) {  
        return "";  
    }  
}  
  
// 用户服务代理  
class UserServiceProxy implements UserService {  
    private static final Logger logger = LoggerFactory.getLogger(UserServiceProxy.class);  
  
    private final UserService userService;  
  
    public UserServiceProxy(UserService userService) {  
        this.userService = userService;  
    }  

	// 使用代理模式记录日志请求 实现日志解耦
    @Override  
    public String login(String username, String password, String code) {  
        logger.info("用户登录请求,用户名:{}, 密码:{}, 验证码: {}", username, password, code);  
        String token = userService.login(username, password, code);  
        logger.info("用户登录完成,登录结果:{}", token);  
        return token;  
    }  
}

行为模式

责任链模式

责任链模式允许将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给下一个处理者。(Spring 的拦截器链和 GoFiber 中的中间件机制都是责任链模式) 适用场景:

  • 需要使用不同方式处理不同种类请求,且请求类型和顺序未知时
  • 必须按一定顺序执行多个处理器时
  • 存在大量 if、else if 时,可以选择使用责任链模式重构
// 成绩处理器  
interface ScoreHandler {  
    void handler(long studentId, double score);  
}  
  
abstract class AbstractScoreHandler implements ScoreHandler {  
    protected ScoreHandler nextHandler;  
  
    public void setNext(ScoreHandler nextHandler) {  
        this.nextHandler = nextHandler;  
    }  
}  
  
// 优秀成绩处理  
class FineScoreHandler extends AbstractScoreHandler {  
    @Override  
    public void handler(long studentId, double score) {  
        if (score >= 90) {  
            System.out.println("优秀");  
            return;  
        }  
        if (this.nextHandler != null) {  
            this.nextHandler.handler(studentId, score);  
        }  
    }  
}  
  
// 良好成绩处理  
class GoodScoreHandler extends AbstractScoreHandler {  
    @Override  
    public void handler(long studentId, double score) {  
        if (score < 90 && score >= 80) {  
            System.out.println("良好");  
            return;  
        }  
        if (this.nextHandler != null) {  
            this.nextHandler.handler(studentId, score);  
        }  
    }  
}  
  
// 及格成绩处理  
class PassScoreHandler extends AbstractScoreHandler {  
    @Override  
    public void handler(long studentId, double score) {  
        if (score < 80 && score >= 60) {  
            System.out.println("及格");  
            return;  
        }  
        if (this.nextHandler != null) {  
            this.nextHandler.handler(studentId, score);  
        }  
    }  
}  
  
// 不及格成绩处理  
class FailedScoreHandler extends AbstractScoreHandler {  
    @Override  
    public void handler(long studentId, double score) {  
        if (score < 60 && score >= 0) {  
            System.out.println("不及格");  
            return;  
        }  
        if (this.nextHandler != null) {  
            this.nextHandler.handler(studentId, score);  
        }  
    }  
}

使用

public class Main {  
    public static void main(String[] args) {  
        FineScoreHandler fineHandler = new FineScoreHandler();  
        GoodScoreHandler goodHandler = new GoodScoreHandler();  
        PassScoreHandler passHandler = new PassScoreHandler();  
        FailedScoreHandler failedHandler = new FailedScoreHandler();  
        // 形成责任链 单一处理器单一职责  
        fineHandler.setNext(goodHandler);  
        goodHandler.setNext(passHandler);  
        passHandler.setNext(failedHandler);  
  
        for (int i = 0; i < 100; i++) {  
            double score = new Random().nextDouble(100);  
            System.out.println("成绩:" + score);  
            fineHandler.handler(1, score);  
        }  
    }  
}

命令模式

命令模式本质上是把方法或请求转换为一个独立对象,可以依据不同的请求将方法参数化、延迟请求执行或将其放入队列中。 适用场景:

  • 需要通过操作参数化对象
  • 需要将操作放入队列中或者远程执行操作
  • 需要实现操作回滚功能
interface Device {  
    void on();  
    void off();  
}  
  
class Tv implements Device {  
    private boolean isRunning = false;  
    @Override  
    public void on() {  
        this.isRunning = true;  
    }  
  
    @Override  
    public void off() {  
        this.isRunning = false;  
    }  
}  
// 命令接口
interface Command {  
    void execute();  
}  

// 将设备开启和关闭的命令单独抽象为对象
class OnCommand implements Command {  
    private final Device device;  
  
    public OnCommand(Device device) {  
        this.device = device;  
    }  
  
    @Override  
    public void execute() {  
        this.device.on();  
    }  
}  
  
class OffCommand implements Command {  
    private final Device device;  
  
    public OffCommand(Device device) {  
        this.device = device;  
    }  
  
    @Override  
    public void execute() {  
        this.device.off();  
    }  
}  
// 为按钮绑定命令 当按钮被点击时触发
class Button {  
    private final Command command;  
  
    public Button(Command command) {  
        this.command = command;  
    }  
  
    public void click() {  
        this.command.execute();  
    }  
}

使用

public class Main {  
    public static void main(String[] args) {  
        Device tv = new Tv();  
        Command onCommand = new OnCommand(tv);  
        Command offCommand = new OffCommand(tv);  
        Button onButton = new Button(onCommand);  
        Button offButton = new Button(offCommand);  
		// 通过onCommand命令开启设备
        onButton.click();  
        // 通过offCommand命令关闭设备
        offButton.click();  
    }  
}

迭代器模式

迭代器模式可以在不暴露对象底层数据结构的情况下遍历集合中的所有元素。 适用场景:

  • 当集合为某个对象背后的数据结构时,希望其对客户端隐藏,可以使用迭代器模式
  • 减少重复的遍历代码
  • 希望可以遍历不同的数据结构
// 迭代器接口
interface Iterator<T> {  
    boolean hashNext();  
    T getNext();  
}  

// 用户迭代器
class UserIterator implements Iterator {  
    private final List<User> userList;  
    private int index;  
  
    public UserIterator(List<User> userList) {  
        this.userList = userList;  
        this.index = 0;  
    }  
    @Override  
    public boolean hashNext() {  
        return index < this.userList.size();  
    }  
  
    @Override  
    public Object getNext() {  
        if (this.hashNext()) {  
            return this.userList.get(this.index++);  
        }  
        return null;  
    }  
}  
  
interface Collection {  
    Iterator createIterator();  
}  
  
record User(int id, String name, int age) {}  
  
class UserCache implements Collection {  
    private final Map<String, User> cacheMap = new HashMap<>();  
  
    @Override
    // 创建迭代器
    public Iterator createIterator() {  
        List<User> userList = new ArrayList<>(cacheMap.size());  
        cacheMap.forEach((k, v) -> userList.add(v));  
        return new UserIterator(userList);  
    }  
  
    public void addUser(User user) {  
        this.cacheMap.put(user.name(), user);  
    }  
}

使用

public class Main {  
    public static void main(String[] args) {  
        User user1 = new User(1, "a", 1);  
        User user2 = new User(2, "b", 2);  
        UserCache userCache = new UserCache();  
        userCache.addUser(user1);  
        userCache.addUser(user2);  
        Iterator userIterator = userCache.createIterator();  
        // 通过迭代器遍历
        while (userIterator.hashNext()) {  
            System.out.println(userIterator.getNext());  
        }  
    }  
}

中介者模式

中介模式可以减少对象之间混乱的依赖关系,会限制对象之间的直接交互,迫使通过中介对象进行合作。 适用场景:

  • 需要解耦一些高耦合的对象时
  • 组件过于依赖另一个组件而无法重用时

备忘录模式

备忘录模式可以在不暴露对象实现细节的情况下保存和恢复对象之前的状态。 适用场景:

  • 需要创建快照以便随时恢复其状态时

观察者模式

观察者模式是一种订阅机制,可以在对象事件发生时通知多个观察该对象的客户端。 适用场景:

  • 当对象状态的改变关联到多个其它对象时
  • 某个对象在有限时间内需要观察某个对象
interface EventListener<T> {  
    void update(String eventType, T value);  
}  
  
// 事件触发后记录日志  
class TradeEventListener implements EventListener<String> {  
    @Override  
    public void update(String eventType, String value) {  
        System.out.println("通知类型:" + eventType + ", 内容:" + value);  
    }  
}  
  
// 事件触发后发送通知  
class NotifyEventListener implements EventListener<String> {  
    @Override  
    public void update(String eventType, String value) {  
        // 向指定地址发送通知  
    }  
}  
  
// 事件管理器  
class EventManager {  
    private final Map<String, HashSet<EventListener<Object>>> eventMap = new HashMap<>();  
  
    public EventManager(String... eventTypes) {  
        for (String eventType : eventTypes) {  
            if (eventMap.containsKey(eventType)) {  
                continue;  
            }  
            eventMap.put(eventType, new HashSet<>());  
        }  
    }  
    // 订阅事件  
    public <T> void subscribe(String eventType, EventListener<T> eventListener) {  
        HashSet<EventListener<Object>> set = eventMap.get(eventType);  
        set.add((EventListener<Object>) eventListener);  
    }  
    // 取消订阅  
    public <T> void unsubscribe(String eventType, EventListener<T> eventListener) {  
        HashSet<EventListener<Object>> set = eventMap.get(eventType);  
        set.remove(eventListener);  
    }  
  
    public <T> void notify(String eventType, T value) {  
        HashSet<EventListener<Object>> set = eventMap.get(eventType);  
        set.forEach(event -> event.update(eventType, value));  
    }  
}  
  
class Device {  
    private final EventManager eventManager;  
    public Device() {  
        this.eventManager = new EventManager("on", "off");  
    }  
    // 开启或关闭时触发事件  
    public void on() {  
        this.eventManager.notify("on", "power on");  
    }  
    public void off() {  
        this.eventManager.notify("off", "power off");  
    }  
}

使用

public class Main {  
    public static void main(String[] args) {  
        Device device = new Device();  
        EventListener<String> tradeListener = new TradeEventListener();  
        EventListener<String> notifyListener = new NotifyEventListener();  
        device.eventManager.subscribe("on", tradeListener);  
        device.eventManager.subscribe("off", notifyListener);  
        device.on();  
        device.off();  
    }  
}

状态模式

状态模式可以在对象的内部状态发生变化时自动更改其行为。 适用场景:

  • 对象需要根据自身状态进行不同的行为,且状态数量非常多
  • 相似状态和基于条件的状态机存在许多重复代码时

策略模式

策略模式可以将每种算法分别放入独立的类中,使算法的对象可以相互替换。 适用场景:

  • 需要在对象中使用各种不同的算法,并可以在运行时切换
  • 抽取执行某些行为时略有不同的相似类
  • 隔离类的业务逻辑和算法实现细节
  • 替换复杂的条件语句,实现算法的切换
// 订单类
record Order(String orderNo, BigDecimal amount, int type) {}  

// 支付接口
interface Paypal {  
    String pay(Order order);  
}  

// 微信支付策略
class WechatPaypal implements Paypal {  
    @Override  
    public String pay(Order order) {  
        // 实现微信支付逻辑  
        return "";  
    }  
}  
// 字符串支付策略
class AlipayPaypal implements Paypal {  
    @Override  
    public String pay(Order order) {  
        // 实现支付宝支付逻辑  
        return "";  
    }  
}

使用

public class Main {  
    public static void main(String[] args) {  
        Order order = new Order("1", BigDecimal.valueOf(1.11), 1);  
        Paypal paypal;
        // 根据订单类型的不同选择不同的支付策略
        if (order.type() == 1) {  
            paypal = new WechatPaypal();  
        } else {  
            paypal = new AlipayPaypal();  
        }  
        String paypalUrl = paypal.pay(order);  
    }  
}

模板方法模式

模板方法模式用于在超类中定义一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。 适用场景:

  • 希望客户端扩展某个特定算法步骤、而不是整个算法或其结构
  • 多个类的算法出一些特定细节的区别外几乎完全一样时
// 数据分析接口 只有格式化数据的算法有区别
interface DataAnalyze {  
    String formatData(String data);  
  
    // 使用default实现默认的数据分析逻辑 在每个实现类中都可以使用  
    default void analyze(String jsonData) {  
        // 详细的数据分析逻辑  
    }  
}  
  
class CSVDataAnalyze implements DataAnalyze {  
    // 将csv数据转换为json数据  
    @Override  
    public String formatData(String data) {  
        return "";  
    }  
}  
  
class XMLDataAnalyze implements DataAnalyze {  
    // 将xml数据转换为json数据  
    @Override  
    public String formatData(String data) {  
        return "";  
    }  
}

使用

public class Main {  
    public static void main(String[] args) {  
        DataAnalyze dataAnalyze;  
        String data = "<user><id>1</id></user>";  
        String dataType = "xml";  
        // 通过数据类型判断使用哪一个模板方法 其数据分析的逻辑都是一致的
        if ("xml".equals(dataType)) {  
            dataAnalyze = new XMLDataAnalyze();  
        } else {  
            dataAnalyze = new CSVDataAnalyze();  
        }  
        String jsonData = dataAnalyze.formatData(data);  
        dataAnalyze.analyze(jsonData);  
    }  
}

访问者模式

访问者模式用于将算法和与其所作用的对象隔离开 适用场景:

  • 需要对复杂对象结构中的所有元素执行某些操作时
  • 清理辅助行为的业务逻辑
  • 当某个行为只在类层次结构中的某些类中有意义时

关联文章

0 条评论