设计模式介绍

什么是设计模式,了解哪些设计模式
设计模式是指在软件开发中,经过总结和提炼出来的一些通用的解决方案,用于解决常见的设计问题,是一种在特定环境下解决一类重复性问题的套路。

设计模式可以分为三种类型:
    创建型模式:用于描述对象的创建过程,包括简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、原型模式和建造者模式。
    结构型模式:用于描述类或对象之间的组合和关联关系,包括适配器模式、桥接模式、装饰器模式、外观模式、享元模式和组合模式。
    行为型模式:用于描述对象之间的通信和协作,包括模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式和策略模式等。

常见的设计模式包括:
    单例模式:确保一个类只有一个实例,并提供全局访问点。
    工厂模式:提供一个通用的接口来创建对象,根据不同的输入参数返回不同的实例。
    适配器模式:将一个类的接口转换成客户端所期望的另一个接口,以便兼容不同的接口。
    观察者模式:定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知。
    模板方法模式:定义一个算法的骨架,并允许子类为一个或多个步骤提供实现。
    建造者模式:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
    策略模式:定义一系列算法,将每个算法都封装起来,并使它们之间可以互换。

这些设计模式都是经过实践验证和总结出来的一些通用解决方案,可以有效地提高代码的可读性、可维护性和可扩展性。但是需要根据具体的场景和需求来选择合适的设计模式,不能过度使用或滥用设计模式。
设计模式:单例设计模式
单例模式是一种常用的软件设计模式,它保证某个类只能有一个实例,并提供一个全局访问点来访问该实例。简单来说,单例模式就是限制一个类只能创建一个对象,保证全局唯一性。
在实现单例模式时,一般需要满足以下几个要点:
	私有化该类的构造方法,防止外部直接创建对象;
	提供一个静态方法来返回该类的唯一实例;
	在第一次调用该静态方法时创建实例,并将其保存下来,以后每次调用该静态方法时都返回该实例。
	单例模式适用于需要全局唯一性的对象,如配置信息、日志记录器、数据库连接等。
饥汉型 和 懒汉型
饥汉型和懒汉型是单例模式的两种不同实现方式。
	饥汉型是在类加载时就创建实例,并且在整个程序运行期间都一直存在,因此也称为饿汉式单例模式。饥汉型的实现方式通常是将构造方法私有化,然后提供一个静态的、公共的、不可变的实例变量,该变量在类加载时就被创建。由于在类加载时就创建了实例,因此可以保证线程安全,但也会导致程序启动时的一定的性能损失。
	懒汉型是在第一次使用时才创建实例,并且在整个程序运行期间只存在一个实例,因此也称为懒汉式单例模式。懒汉型的实现方式通常是将构造方法私有化,然后提供一个静态的、公共的、可变的实例变量,在第一次使用时才创建实例。由于在多线程环境下存在并发问题,因此需要加锁来保证线程安全。懒汉型相比饥汉型的优点是可以避免启动时的性能损失,但缺点是可能存在线程安全问题和实现复杂度高的问题。
设计模式:简单工厂模式
简单工厂模式是一种创建型设计模式,它提供了一个统一的工厂类来创建不同的产品对象,使得客户端不需要知道具体产品类的名称,只需要知道它们的公共接口即可。

简单工厂模式的主要角色包括:
	工厂类(Factory):负责创建各种产品对象的工厂类,它是简单工厂模式的核心,包含一个用于创建产品对象的工厂方法。
	抽象产品类(Product):定义产品的公共接口,是具体产品类的父类。
	具体产品类(ConcreteProduct):实现抽象产品类定义的公共接口,是被创建的对象。
简单工厂模式的流程如下:
	客户端向工厂类请求一个产品对象。
	工厂类根据客户端请求的产品类型创建相应的产品对象并返回。
	客户端使用返回的产品对象进行相应的操作。

简单工厂模式的优点在于可以封装对象的创建过程,客户端不需要知道具体的产品类名,只需要知道产品类的公共接口。同时,如果需要更改产品对象,只需要修改工厂类即可。缺点在于如果需要添加新的产品类,则需要修改工厂类的代码,违背了“开放-封闭”原则。
设计模式:适配器模式
适配器模式是一种结构型设计模式,它将一个类的接口转换为另一个客户端希望的接口。它允许不兼容的接口之间进行通信,使得原本无法一起工作的类能够协同工作。适配器模式常常被用于现有系统的改进和升级中,它能够提高代码的复用性和可扩展性。

适配器模式包含以下几个主要角色:
	目标接口(Target):客户端希望使用的接口,也就是适配器将要转换成的接口。
	源接口(Adaptee):需要被适配的接口,也就是客户端原本无法直接使用的接口。
	适配器(Adapter):将源接口转换成目标接口的中间件。

以下是一个简单的示例,展示了如何使用适配器模式将一个旧的计算机类的接口转换为新的接口,以便客户端能够使用它:

# 目标接口
class Computer:
    def __init__(self, name):
        self.name = name

    def run(self):
        pass

# 源接口
class OldComputer:
    def __init__(self, name):
        self.name = name

    def start(self):
        print(f"{self.name} is starting")

# 适配器
class ComputerAdapter(Computer):
    def __init__(self, old_computer):
        self.old_computer = old_computer

    def run(self):
        self.old_computer.start()

# 客户端代码
if __name__ == '__main__':
    # 使用适配器将旧接口转换成新接口
    old_computer = OldComputer("Old Computer")
    computer = ComputerAdapter(old_computer)

    # 客户端使用新接口调用旧接口的方法
    computer.run()  # 输出: Old Computer is starting
设计模式:工厂方法模式
工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但是具体创建哪个对象由子类决定。也就是说,工厂方法模式将对象的创建延迟到了子类中去实现。

工厂方法模式的主要角色包括:
	抽象产品(Product):定义了产品的抽象接口,是具体产品类的父类。
	具体产品(ConcreteProduct):实现抽象产品定义的接口,是被创建的对象。
	抽象工厂(Factory):定义了创建抽象产品的接口,是具体工厂类的父类。
	具体工厂(ConcreteFactory):实现抽象工厂定义的接口,创建具体产品的对象。
工厂方法模式的流程如下:
	客户端向具体工厂请求一个产品对象。
	具体工厂根据客户端请求的产品类型创建相应的产品对象并返回。
	客户端使用返回的产品对象进行相应的操作。
	工厂方法模式的优点在于将具体产品的创建过程封装到了具体工厂中,客户端不需要知道具体的产品类名,只需要知道产品类的公共接口。同时,如果需要添加新的产品类,则只需要添加具体产品和具体工厂即可,不需要修改已有的代码。缺点在于需要创建大量的具体工厂类,增加了系统的复杂度。
Java 工厂方法模式实现
// 定义抽象产品接口或抽象类。
public interface Product {
    void use();
}

// 定义具体产品类实现抽象产品接口或抽象类。
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("use ConcreteProductA");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("use ConcreteProductB");
    }
}

// 定义抽象工厂接口或抽象类。
public interface Factory {
    Product createProduct();
}

// 定义具体工厂类实现抽象工厂接口或抽象类,负责创建具体产品类的实例。
public class ConcreteFactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

public class ConcreteFactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 客户端使用具体工厂创建产品对象,并使用该对象调用产品方法。
public class Client {
    public static void main(String[] args) {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.use();

        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.use();
    }
}
设计模式:抽象工厂模式
抽象工厂模式是一种创建型设计模式,它提供了一种将相关对象组合成族群的方式,而无需指定它们的具体类。抽象工厂模式允许客户端通过接口或抽象类来创建一组相关的产品,而不必指定实际的实现类。这使得客户端代码可以独立于实际实现,从而增强了程序的可扩展性和灵活性。

该模式包含四个主要角色:抽象工厂(Abstract Factory)、具体工厂(Concrete Factory)、抽象产品(Abstract Product)和具体产品(Concrete Product)。抽象工厂定义了创建产品族的接口,具体工厂实现了这个接口来创建具体的产品,抽象产品定义了产品的接口,具体产品实现了这个接口来提供具体的实现。

以下是一个简单的示例,展示了如何使用抽象工厂模式创建一组不同的 GUI 组件,包括按钮和文本框。

# 抽象工厂
class GUIFactory:
    def create_button(self):
        pass

    def create_text_field(self):
        pass

# 具体工厂1
class WindowsFactory(GUIFactory):
    def create_button(self):
        return WindowsButton()

    def create_text_field(self):
        return WindowsTextField()

# 具体工厂2
class MacFactory(GUIFactory):
    def create_button(self):
        return MacButton()

    def create_text_field(self):
        return MacTextField()

# 抽象产品1
class Button:
    def click(self):
        pass

# 具体产品1.1
class WindowsButton(Button):
    def click(self):
        print("Windows button clicked")

# 具体产品1.2
class MacButton(Button):
    def click(self):
        print("Mac button clicked")

# 抽象产品2
class TextField:
    def input(self):
        pass

# 具体产品2.1
class WindowsTextField(TextField):
    def input(self):
        print("Windows text field input")

# 具体产品2.2
class MacTextField(TextField):
    def input(self):
        print("Mac text field input")

# 客户端代码
if __name__ == '__main__':
    os_type = 'Windows'
    if os_type == 'Windows':
        factory = WindowsFactory()
    elif os_type == 'Mac':
        factory = MacFactory()

    button = factory.create_button()
    text_field = factory.create_text_field()

    button.click()
    text_field.input()
 
# 在上述代码中,我们定义了一个抽象工厂类 GUIFactory 和两个具体工厂类 WindowsFactory 和 MacFactory。每个具体工厂类都实现了抽象工厂的方法来创建具体的产品对象。我们还定义了抽象产品类 Button 和 TextField,以及两个具体产品类 WindowsButton、MacButton 和 WindowsTextField、MacTextField。客户端代码根据操作系统类型来选择具体工厂,并使用该工厂来创建一组相关的产品。最后,客户端代码可以通过产品的公共接口来使用这些产品。
设计模式:观察者模式
观察者模式是一种行为设计模式,它允许对象之间的一对多依赖关系,当一个对象的状态发生改变时,它的所有依赖对象都将得到通知并自动更新。
	该模式的主要角色包括被观察者(Subject)和观察者(Observer)。被观察者维护一个观察者列表,并提供了用于添加或删除观察者的方法。当被观察者的状态发生改变时,它会通知所有的观察者,让它们进行相应的处理。
	观察者模式的优点在于它可以将观察者和被观察者解耦,使它们可以独立地进行修改和扩展。同时,它还可以让我们在不修改代码的情况下添加新的观察者,从而增强程序的可扩展性。

以下是一个简单的示例,展示了如何使用观察者模式实现一个简单的气象站,当气象数据发生变化时,它会通知所有的观察者。

class Subject:
    def __init__(self):
        self.observers = []
        self.data = None

    def attach(self, observer):
        self.observers.append(observer)

    def detach(self, observer):
        self.observers.remove(observer)

    def notify(self):
        for observer in self.observers:
            observer.update(self.data)

    def set_data(self, data):
        self.data = data
        self.notify()

class Observer:
    def update(self, data):
        pass

class WeatherStation(Subject):
    def set_temperature(self, temperature):
        self.set_data(temperature)

class PhoneDisplay(Observer):
    def update(self, data):
        print(f"Current temperature: {data}")

class EmailAlert(Observer):
    def update(self, data):
        if data > 30:
            print("It's too hot, send an email alert!")

station = WeatherStation()
phone_display = PhoneDisplay()
email_alert = EmailAlert()
station.attach(phone_display)
station.attach(email_alert)
station.set_temperature(25)
station.set_temperature(35)

# 在上述代码中,我们定义了一个 Subject 类作为被观察者,它维护一个观察者列表,当状态发生改变时,它会通知所有的观察者。我们还定义了一个 Observer 类作为观察者的基类,以及两个具体的观察者 PhoneDisplay 和 EmailAlert。最后,我们定义了一个 WeatherStation 类作为具体的被观察者,它可以设置温度数据,并将其通知给所有的观察者。在 main 函数中,我们创建了一个 WeatherStation 对象,并将 PhoneDisplay 和 EmailAlert 观察者对象添加到它的观察者列表中。当我们调用 set_temperature 方法时,它会通知所有的观察者,让它们进行相应的处理。

posted on 2023-03-09 15:29  cloud_wh  阅读(36)  评论(0编辑  收藏  举报

导航