之前已经讨论过抽象与具体,但这里更深入地探讨,并结合更多的实例。
抽象与具体是软件开发中的一对基本方法,抽象帮助忽略细节,把握本质;具体则关注实现细节,将抽象转化为可执行的代码。
在软件开发的各个阶段,都会用到抽象与具体:
需求分析:抽象出核心业务概念,具体化为用户故事或用例。
设计:抽象出接口和架构,具体化为类和模块的实现。
编码:抽象出函数和数据结构,具体化为代码逻辑。
测试:抽象出测试场景,具体化为测试用例。
下面用三个例子来展示抽象与具体在不同语言中的应用。
例子1:图形渲染引擎
抽象:可渲染的对象(Renderable)
具体:圆形(Circle)、矩形(Rectangle)等具体形状
例子2:数据处理管道
抽象:数据处理步骤(DataStep)
具体:过滤步骤(FilterStep)、转换步骤(TransformStep)
例子3:网络请求处理
抽象:请求处理器(RequestHandler)
具体:用户请求处理器(UserRequestHandler)、订单请求处理器(OrderRequestHandler)
下面将用Python、Java和C++分别实现例子1(图形渲染引擎)来展示抽象与具体。
注意:由于C++没有接口的概念,使用抽象类。
抽象与具体:软件开发的核心思维方法
一、 抽象与具体方法论
1. 抽象(Abstraction)
- 核心思想:从具体事物中提取本质特征,忽略非本质细节,形成通用概念或模型。
- 目的:降低复杂性,提高复用性,建立清晰的边界和接口。
- 实现方式:
- 数据抽象:定义数据类型及其操作,隐藏实现细节
- 过程抽象:将复杂过程封装为函数或方法
- 控制抽象:定义控制流程的通用模式
- 接口抽象:定义组件间的交互契约
2. 具体(Concretization)
- 核心思想:将抽象概念实例化,提供具体的实现和细节。
- 目的:实现功能,提供实际价值,验证抽象的有效性。
- 实现方式:
- 实例化:创建抽象类的具体对象
- 实现:提供接口或抽象方法的具体代码
- 特化:为通用概念提供特定场景的实现
- 优化:根据具体场景调整实现细节
3. 两者关系
抽象与具体是软件开发中的基本辩证关系:
- 抽象提供蓝图和规范
- 具体提供实现和细节
- 良好实践:面向抽象编程,依赖抽象而非具体实现
二、 实例说明:跨平台UI框架设计
我们将通过设计一个跨平台UI框架,展示抽象与具体在软件开发中的应用。
第一阶段:抽象设计 - 定义通用接口
# Python - 抽象层设计:定义跨平台UI组件的通用接口
from abc import ABC, abstractmethod
from typing import Protocol, runtime_checkable
# 抽象1:窗口系统抽象
class Window(ABC):
"""窗口抽象:定义所有平台窗口的通用接口"""
@abstractmethod
def show(self) -> None:
"""显示窗口"""
pass
@abstractmethod
def hide(self) -> None:
"""隐藏窗口"""
pass
@abstractmethod
def set_title(self, title: str) -> None:
"""设置窗口标题"""
pass
@abstractmethod
def get_size(self) -> tuple[int, int]:
"""获取窗口大小"""
pass
@abstractmethod
def set_size(self, width: int, height: int) -> None:
"""设置窗口大小"""
pass
# 抽象属性
@property
@abstractmethod
def is_visible(self) -> bool:
"""窗口是否可见"""
pass
@property
@abstractmethod
def title(self) -> str:
"""窗口标题"""
pass
# 抽象2:UI控件抽象
class UIControl(ABC):
"""UI控件抽象:定义所有控件的通用行为"""
@abstractmethod
def render(self) -> str:
"""渲染控件,返回表示控件的字符串"""
pass
@abstractmethod
def handle_event(self, event: 'UIEvent') -> bool:
"""处理UI事件,返回是否已处理"""
pass
@abstractmethod
def set_enabled(self, enabled: bool) -> None:
"""启用或禁用控件"""
pass
# 抽象属性:位置和大小
@property
@abstractmethod
def position(self) -> tuple[int, int]:
"""控件位置 (x, y)"""
pass
@position.setter
@abstractmethod
def position(self, value: tuple[int, int]) -> None:
pass
@property
@abstractmethod
def size(self) -> tuple[int, int]:
"""控件大小 (width, height)"""
pass
# 抽象3:布局管理器抽象
class LayoutManager(ABC):
"""布局管理器抽象:定义控件排列的通用算法"""
@abstractmethod
def add_control(self, control: UIControl) -> None:
"""添加控件到布局"""
pass
@abstractmethod
def remove_control(self, control: UIControl) -> None:
"""从布局中移除控件"""
pass
@abstractmethod
def arrange(self, container_size: tuple[int, int]) -> None:
"""根据容器大小排列所有控件"""
pass
@abstractmethod
def get_preferred_size(self) -> tuple[int, int]:
"""获取布局的首选大小"""
pass
# 抽象4:UI事件系统抽象
@runtime_checkable
class UIEventHandler(Protocol):
"""UI事件处理器抽象:使用Protocol定义接口"""
def on_click(self, source: UIControl, x: int, y: int) -> None:
"""点击事件处理"""
...
def on_key_press(self, source: UIControl, key: str) -> None:
"""按键事件处理"""
...
def on_mouse_move(self, source: UIControl, x: int, y: int) -> None:
"""鼠标移动事件处理"""
...
# 抽象5:UI构建器抽象(工厂模式)
class UIFactory(ABC):
"""UI工厂抽象:创建平台相关的UI组件"""
@abstractmethod
def create_window(self, title: str) -> Window:
"""创建窗口"""
pass
@abstractmethod
def create_button(self, text: str) -> 'Button':
"""创建按钮"""
pass
@abstractmethod
def create_textbox(self, placeholder: str = "") -> 'Textbox':
"""创建文本框"""
pass
@abstractmethod
def create_label(self, text: str) -> 'Label':
"""创建标签"""
pass
@abstractmethod
def create_layout(self, layout_type: str) -> LayoutManager:
"""创建布局管理器"""
pass
# 抽象6:主题系统抽象
class Theme(ABC):
"""主题抽象:定义UI的外观和感觉"""
@property
@abstractmethod
def name(self) -> str:
"""主题名称"""
pass
@abstractmethod
def get_color(self, color_type: str) -> str:
"""获取颜色(十六进制或RGB)"""
pass
@abstractmethod
def get_font(self, font_type: str) -> dict:
"""获取字体配置"""
pass
@abstractmethod
def get_padding(self, element_type: str) -> tuple[int, int, int, int]:
"""获取内边距 (上, 右, 下, 左)"""
pass
# 抽象7:高级UI组件抽象(组合模式)
class Container(UIControl, ABC):
"""容器抽象:可以包含其他控件的控件"""
def __init__(self):
self._controls: list[UIControl] = []
self._layout: LayoutManager = None
@abstractmethod
def add_control(self, control: UIControl) -> None:
"""添加子控件"""
self._controls.append(control)
@abstractmethod
def remove_control(self, control: UIControl) -> None:
"""移除子控件"""
self._controls.remove(control)
@abstractmethod
def clear_controls(self) -> None:
"""清空所有子控件"""
self._controls.clear()
def set_layout(self, layout: LayoutManager) -> None:
"""设置布局管理器"""
self._layout = layout
def render(self) -> str:
"""渲染容器及其所有子控件"""
result = [f"<Container position={self.position} size={self.size}>"]
for control in self._controls:
result.append(f" {control.render()}")
result.append("</Container>")
return "\n".join(result)
// Java - 抽象层设计:使用接口和抽象类定义UI框架抽象
package ui.framework;
import java.util.List;
// 抽象1:UI组件接口
public interface UIComponent {
// 抽象方法:渲染组件
String render();
// 抽象方法:处理事件
boolean handleEvent(UIEvent event);
// 抽象方法:获取组件类型
String getComponentType();
// 抽象属性:位置和大小(通过getter/setter)
Position getPosition();
void setPosition(Position position);
Size getSize();
void setSize(Size size);
// 默认方法:Java 8+ 允许接口有默认实现
default boolean isVisible() {
return true;
}
default void show() {
System.out.println("Showing component: " + getComponentType());
}
default void hide() {
System.out.println("Hiding component: " + getComponentType());
}
}
// 抽象2:可绘制接口
public interface Drawable {
void draw(GraphicsContext context);
void update(double deltaTime);
boolean contains(Point point);
}
// 抽象3:事件处理器接口(泛型)
public interface EventHandler<T extends UIEvent> {
void handle(T event);
}
// 抽象4:布局管理器接口
public interface LayoutManager {
void layoutComponents(List<UIComponent> components, Container container);
Size calculatePreferredSize(List<UIComponent> components);
void setConstraint(UIComponent component, LayoutConstraint constraint);
}
// 抽象5:UI工厂抽象类
public abstract class UIFactory {
// 抽象工厂方法
public abstract Button createButton(String text);
public abstract TextField createTextField(String placeholder);
public abstract Label createLabel(String text);
public abstract Window createWindow(String title);
public abstract Panel createPanel();
// 模板方法:创建带有默认配置的组件
public final Button createDefaultButton(String text) {
Button button = createButton(text);
button.setSize(new Size(100, 40));
button.setStyle(Style.DEFAULT);
return button;
}
// 钩子方法:子类可以覆盖
protected Style getDefaultButtonStyle() {
return Style.DEFAULT;
}
}
// 抽象6:主题抽象类
public abstract class Theme {
private final String name;
protected Theme(String name) {
this.name = name;
}
public String getName() {
return name;
}
// 抽象方法:获取颜色
public abstract Color getPrimaryColor();
public abstract Color getSecondaryColor();
public abstract Color getTextColor();
public abstract Color getBackgroundColor();
// 抽象方法:获取字体
public abstract Font getTitleFont();
public abstract Font getBodyFont();
public abstract Font getButtonFont();
// 模板方法:应用主题到组件
public final void applyTo(UIComponent component) {
if (component instanceof ThemedComponent) {
ThemedComponent themed = (ThemedComponent) component;
themed.applyTheme(this);
}
}
// 抽象方法:创建样式对象
public abstract Style createStyle(String styleName);
}
// 抽象7:命令模式抽象
public abstract class UICommand {
private final String name;
protected final UIComponent target;
protected UICommand(String name, UIComponent target) {
this.name = name;
this.target = target;
}
public String getName() {
return name;
}
// 抽象方法:执行命令
public abstract void execute();
// 抽象方法:撤销命令
public abstract void undo();
// 钩子方法:命令是否可执行
public boolean canExecute() {
return target != null && target.isVisible();
}
}
// 抽象8:观察者模式抽象
public abstract class ObservableUIComponent implements UIComponent {
private List<ComponentObserver> observers = new ArrayList<>();
public void addObserver(ComponentObserver observer) {
observers.add(observer);
}
public void removeObserver(ComponentObserver observer) {
observers.remove(observer);
}
protected void notifyObservers(String eventType, Object data) {
for (ComponentObserver observer : observers) {
observer.onComponentEvent(this, eventType, data);
}
}
// 观察者接口
public interface ComponentObserver {
void onComponentEvent(UIComponent source, String eventType, Object data);
}
}
// 抽象9:状态模式抽象
public abstract class UIState {
protected final UIComponent context;
protected UIState(UIComponent context) {
this.context = context;
}
// 抽象方法:状态行为
public abstract void handleClick(Point clickPoint);
public abstract void handleKeyPress(String key);
public abstract void handleMouseMove(Point position);
// 状态转换
public abstract void transitionTo(UIState nextState);
// 获取状态名称
public abstract String getStateName();
}
// 值对象抽象
public abstract class ValueObject {
// 值对象应该是不可变的
@Override
public abstract boolean equals(Object obj);
@Override
public abstract int hashCode();
@Override
public abstract String toString();
// 验证方法
protected abstract void validate();
}
// C++ - 抽象层设计:使用抽象类和模板定义UI框架抽象
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <functional>
// 抽象1:UI组件抽象类
class UIComponent {
public:
virtual ~UIComponent() = default;
// 纯虚函数:渲染组件
virtual void render() const = 0;
// 纯虚函数:处理事件
virtual bool handleEvent(const std::string& eventType, void* eventData) = 0;
// 纯虚函数:获取组件类型
virtual std::string getType() const = 0;
// 虚函数:可以有默认实现
virtual void update(float deltaTime) {
// 默认什么都不做
}
// 抽象属性:位置和大小
struct Point { int x; int y; };
struct Size { int width; int height; };
virtual Point getPosition() const = 0;
virtual void setPosition(Point position) = 0;
virtual Size getSize() const = 0;
virtual void setSize(Size size) = 0;
// 虚析构函数确保正确清理
virtual ~UIComponent() {}
};
// 抽象2:可绘制接口(多重继承)
class Drawable {
public:
virtual ~Drawable() = default;
virtual void draw() const = 0;
virtual bool isVisible() const { return true; }
// 模板方法模式
void renderWithStyle() const {
if (isVisible()) {
beginDraw();
draw();
endDraw();
}
}
protected:
virtual void beginDraw() const {
std::cout << "开始绘制" << std::endl;
}
virtual void endDraw() const {
std::cout << "结束绘制" << std::endl;
}
};
// 抽象3:事件系统抽象
class EventEmitter {
public:
using EventHandler = std::function<void(void*)>;
virtual ~EventEmitter() = default;
// 注册事件处理器
virtual void on(const std::string& eventName, EventHandler handler) = 0;
// 触发事件
virtual void emit(const std::string& eventName, void* eventData = nullptr) = 0;
// 移除事件处理器
virtual void off(const std::string& eventName) = 0;
};
// 抽象4:UI工厂抽象类(模板方法模式)
template<typename T>
class UIFactory {
public:
// 模板方法:创建并配置组件
std::unique_ptr<T> create(const std::string& name) {
auto component = createComponent(name);
initializeComponent(component.get());
applyDefaultStyle(component.get());
return component;
}
// 工厂方法:子类必须实现
virtual std::unique_ptr<T> createComponent(const std::string& name) = 0;
protected:
// 钩子方法:子类可以覆盖
virtual void initializeComponent(T* component) {
component->setSize({100, 50});
}
virtual void applyDefaultStyle(T* component) {
// 默认样式
}
};
// 抽象5:布局策略抽象(策略模式)
class LayoutStrategy {
public:
virtual ~LayoutStrategy() = default;
// 纯虚函数:布局算法
virtual void applyLayout(std::vector<UIComponent*>& components,
const UIComponent::Size& containerSize) = 0;
// 虚函数:计算首选大小
virtual UIComponent::Size calculatePreferredSize(
const std::vector<UIComponent*>& components) = 0;
// 虚函数:获取策略名称
virtual std::string getName() const = 0;
};
// 抽象6:主题抽象类(桥接模式)
class Theme {
public:
virtual ~Theme() = default;
// 纯虚函数:获取颜色
virtual std::string getColor(const std::string& colorName) const = 0;
// 纯虚函数:获取字体
virtual std::string getFont(const std::string& fontName) const = 0;
// 纯虚函数:获取间距
virtual int getSpacing(const std::string& spacingType) const = 0;
// 模板方法:应用主题到组件
void applyTo(UIComponent* component) const {
if (component) {
applyColors(component);
applyFonts(component);
applySpacing(component);
}
}
protected:
// 钩子方法:子类实现
virtual void applyColors(UIComponent* component) const = 0;
virtual void applyFonts(UIComponent* component) const = 0;
virtual void applySpacing(UIComponent* component) const = 0;
};
// 抽象7:UI构建器抽象(建造者模式)
class UIBuilder {
public:
virtual ~UIBuilder() = default;
// 构建步骤
virtual void buildWindow(const std::string& title) = 0;
virtual void buildMenu() = 0;
virtual void buildToolbar() = 0;
virtual void buildContentArea() = 0;
virtual void buildStatusBar() = 0;
// 获取构建结果
virtual std::unique_ptr<UIComponent> getResult() = 0;
// 模板方法:标准构建流程
std::unique_ptr<UIComponent> constructStandardUI(const std::string& title) {
buildWindow(title);
buildMenu();
buildToolbar();
buildContentArea();
buildStatusBar();
return getResult();
}
};
// 抽象8:访问者模式抽象
class UIComponentVisitor {
public:
virtual ~UIComponentVisitor() = default;
// 访问方法
virtual void visit(class Button* button) = 0;
virtual void visit(class TextBox* textBox) = 0;
virtual void visit(class Label* label) = 0;
virtual void visit(class Container* container) = 0;
// 模板方法:访问组件树
void visitComponentTree(UIComponent* root) {
if (root) {
root->accept(this);
}
}
};
// 可访问的UI组件抽象
class VisitableUIComponent : public UIComponent {
public:
virtual void accept(UIComponentVisitor* visitor) = 0;
};
// 抽象9:状态机抽象(状态模式)
class UIState {
protected:
UIComponent* context_;
public:
UIState(UIComponent* context) : context_(context) {}
virtual ~UIState() = default;
// 状态行为
virtual void onEnter() = 0;
virtual void onExit() = 0;
virtual void onClick(int x, int y) = 0;
virtual void onKeyPress(char key) = 0;
virtual void onMouseMove(int x, int y) = 0;
// 状态转换
virtual void transitionTo(std::unique_ptr<UIState> newState) = 0;
// 获取状态名称
virtual std::string getName() const = 0;
};
// 抽象10:组件装饰器抽象(装饰器模式)
class ComponentDecorator : public UIComponent {
protected:
std::unique_ptr<UIComponent> wrappedComponent_;
public:
ComponentDecorator(std::unique_ptr<UIComponent> component)
: wrappedComponent_(std::move(component)) {}
// 委托给被包装的组件
void render() const override {
if (wrappedComponent_) {
wrappedComponent_->render();
}
}
bool handleEvent(const std::string& eventType, void* eventData) override {
if (wrappedComponent_) {
return wrappedComponent_->handleEvent(eventType, eventData);
}
return false;
}
std::string getType() const override {
if (wrappedComponent_) {
return wrappedComponent_->getType() + "_decorated";
}
return "decorator";
}
// 其他方法类似委托
};
第二阶段:具体实现 - 提供平台特定实现
# Python - 具体实现层:提供各平台的具体实现
import platform
import os
from typing import Dict, Any, Optional
# 具体1:Windows平台实现
class WindowsWindow(Window):
"""Windows平台的具体窗口实现"""
def __init__(self, title: str):
self._title = title
self._visible = False
self._width = 800
self._height = 600
self._hwnd = None # Windows窗口句柄
def show(self) -> None:
if not self._visible:
print(f"[Windows] 显示窗口: {self._title}")
# 实际会调用Win32 API: CreateWindowEx, ShowWindow
self._visible = True
def hide(self) -> None:
if self._visible:
print(f"[Windows] 隐藏窗口: {self._title}")
# 实际会调用Win32 API: ShowWindow(hwnd, SW_HIDE)
self._visible = False
def set_title(self, title: str) -> None:
self._title = title
if self._hwnd:
print(f"[Windows] 设置窗口标题: {title}")
# 实际会调用Win32 API: SetWindowText
def get_size(self) -> tuple[int, int]:
return (self._width, self._height)
def set_size(self, width: int, height: int) -> None:
self._width = width
self._height = height
if self._hwnd:
print(f"[Windows] 设置窗口大小: {width}x{height}")
# 实际会调用Win32 API: SetWindowPos
@property
def is_visible(self) -> bool:
return self._visible
@property
def title(self) -> str:
return self._title
# 具体2:macOS平台实现
class MacWindow(Window):
"""macOS平台的具体窗口实现"""
def __init__(self, title: str):
self._title = title
self._visible = False
self._width = 800
self._height = 600
self._ns_window = None # NSWindow实例
def show(self) -> None:
if not self._visible:
print(f"[macOS] 显示窗口: {self._title}")
# 实际会调用Cocoa API: [window makeKeyAndOrderFront:nil]
self._visible = True
def hide(self) -> None:
if self._visible:
print(f"[macOS] 隐藏窗口: {self._title}")
# 实际会调用Cocoa API: [window orderOut:nil]
self._visible = False
def set_title(self, title: str) -> None:
self._title = title
if self._ns_window:
print(f"[macOS] 设置窗口标题: {title}")
# 实际会调用Cocoa API: [window setTitle:@"title"]
def get_size(self) -> tuple[int, int]:
return (self._width, self._height)
def set_size(self, width: int, height: int) -> None:
self._width = width
self._height = height
if self._ns_window:
print(f"[macOS] 设置窗口大小: {width}x{height}")
# 实际会调用Cocoa API: [window setFrame:display:animate:]
@property
def is_visible(self) -> bool:
return self._visible
@property
def title(self) -> str:
return self._title
# 具体3:Linux平台实现
class LinuxWindow(Window):
"""Linux平台的具体窗口实现(使用GTK)"""
def __init__(self, title: str):
self._title = title
self._visible = False
self._width = 800
self._height = 600
self._gtk_window = None # GtkWindow实例
def show(self) -> None:
if not self._visible:
print(f"[Linux/GTK] 显示窗口: {self._title}")
# 实际会调用GTK API: gtk_widget_show_all(window)
self._visible = True
def hide(self) -> None:
if self._visible:
print(f"[Linux/GTK] 隐藏窗口: {self._title}")
# 实际会调用GTK API: gtk_widget_hide(window)
self._visible = False
def set_title(self, title: str) -> None:
self._title = title
if self._gtk_window:
print(f"[Linux/GTK] 设置窗口标题: {title}")
# 实际会调用GTK API: gtk_window_set_title(window, title)
def get_size(self) -> tuple[int, int]:
return (self._width, self._height)
def set_size(self, width: int, height: int) -> None:
self._width = width
self._height = height
if self._gtk_window:
print(f"[Linux/GTK] 设置窗口大小: {width}x{height}")
# 实际会调用GTK API: gtk_window_resize(window, width, height)
@property
def is_visible(self) -> bool:
return self._visible
@property
def title(self) -> str:
return self._title
# 具体4:Web平台实现
class WebWindow(Window):
"""Web平台的具体窗口实现(使用HTML/CSS/JS)"""
def __init__(self, title: str):
self._title = title
self._visible = False
self._width = 800
self._height = 600
self._element_id = f"window_{id(self)}"
def show(self) -> None:
if not self._visible:
print(f"[Web] 显示窗口: {self._title}")
# 实际会调用JavaScript: document.getElementById(id).style.display='block'
self._visible = True
def hide(self) -> None:
if self._visible:
print(f"[Web] 隐藏窗口: {self._title}")
# 实际会调用JavaScript: document.getElementById(id).style.display='none'
self._visible = False
def set_title(self, title: str) -> None:
self._title = title
print(f"[Web] 设置窗口标题: {title}")
# 实际会调用JavaScript: document.title = title
def get_size(self) -> tuple[int, int]:
return (self._width, self._height)
def set_size(self, width: int, height: int) -> None:
self._width = width
self._height = height
print(f"[Web] 设置窗口大小: {width}x{height}")
# 实际会调用JavaScript: element.style.width/height
@property
def is_visible(self) -> bool:
return self._visible
@property
def title(self) -> str:
return self._title
# 具体5:跨平台按钮实现
class Button(UIControl):
"""按钮的具体实现"""
def __init__(self, text: str, factory: 'UIFactory'):
self._text = text
self._factory = factory
self._position = (0, 0)
self._size = (100, 40)
self._enabled = True
self._click_handlers = []
def render(self) -> str:
platform_name = platform.system()
return f"[{platform_name}] 按钮: {self._text} (位置: {self._position}, 大小: {self._size})"
def handle_event(self, event: 'UIEvent') -> bool:
if event.type == "click" and self._enabled:
print(f"按钮 '{self._text}' 被点击")
for handler in self._click_handlers:
handler(self, event.x, event.y)
return True
return False
def set_enabled(self, enabled: bool) -> None:
self._enabled = enabled
print(f"按钮 '{self._text}' 启用状态: {enabled}")
@property
def position(self) -> tuple[int, int]:
return self._position
@position.setter
def position(self, value: tuple[int, int]) -> None:
self._position = value
@property
def size(self) -> tuple[int, int]:
return self._size
# 具体6:跨平台文本框实现
class TextBox(UIControl):
"""文本框的具体实现"""
def __init__(self, placeholder: str = "", factory: 'UIFactory'):
self._placeholder = placeholder
self._text = ""
self._factory = factory
self._position = (0, 0)
self._size = (200, 30)
self._enabled = True
def render(self) -> str:
display_text = self._text if self._text else self._placeholder
return f"文本框: '{display_text}' (位置: {self._position}, 大小: {self._size})"
def handle_event(self, event: 'UIEvent') -> bool:
if event.type == "key_press" and self._enabled:
self._text += event.key
print(f"文本框输入: {self._text}")
return True
return False
def set_enabled(self, enabled: bool) -> None:
self._enabled = enabled
def get_text(self) -> str:
return self._text
def set_text(self, text: str) -> None:
self._text = text
@property
def position(self) -> tuple[int, int]:
return self._position
@position.setter
def position(self, value: tuple[int, int]) -> None:
self._position = value
@property
def size(self) -> tuple[int, int]:
return self._size
# 具体7:Windows工厂实现
class WindowsUIFactory(UIFactory):
"""Windows平台的具体工厂"""
def create_window(self, title: str) -> Window:
return WindowsWindow(title)
def create_button(self, text: str) -> Button:
return Button(text, self)
def create_textbox(self, placeholder: str = "") -> TextBox:
return TextBox(placeholder, self)
def create_label(self, text: str) -> 'Label':
return Label(text, self)
def create_layout(self, layout_type: str) -> LayoutManager:
if layout_type == "flow":
return FlowLayout()
elif layout_type == "grid":
return GridLayout()
else:
return FlowLayout()
# 具体8:macOS工厂实现
class MacUIFactory(UIFactory):
"""macOS平台的具体工厂"""
def create_window(self, title: str) -> Window:
return MacWindow(title)
def create_button(self, text: str) -> Button:
button = Button(text, self)
button._size = (120, 35) # macOS风格按钮稍大
return button
def create_textbox(self, placeholder: str = "") -> TextBox:
textbox = TextBox(placeholder, self)
textbox._size = (220, 28) # macOS风格文本框
return textbox
def create_label(self, text: str) -> 'Label':
return Label(text, self)
def create_layout(self, layout_type: str) -> LayoutManager:
if layout_type == "flow":
return MacFlowLayout()
elif layout_type == "grid":
return MacGridLayout()
else:
return MacFlowLayout()
# 具体9:流式布局实现
class FlowLayout(LayoutManager):
"""流式布局的具体实现"""
def __init__(self):
self._controls = []
self._h_spacing = 10
self._v_spacing = 10
def add_control(self, control: UIControl) -> None:
self._controls.append(control)
def remove_control(self, control: UIControl) -> None:
if control in self._controls:
self._controls.remove(control)
def arrange(self, container_size: tuple[int, int]) -> None:
x, y = 0, 0
max_row_height = 0
for control in self._controls:
control_size = control.size
# 检查是否需要换行
if x + control_size[0] > container_size[0]:
x = 0
y += max_row_height + self._v_spacing
max_row_height = 0
# 设置控件位置
control.position = (x, y)
# 更新位置和行高
x += control_size[0] + self._h_spacing
max_row_height = max(max_row_height, control_size[1])
def get_preferred_size(self) -> tuple[int, int]:
if not self._controls:
return (0, 0)
total_width = 0
max_height = 0
current_row_width = 0
current_row_height = 0
rows = 1
for control in self._controls:
width, height = control.size
current_row_width += width + self._h_spacing
current_row_height = max(current_row_height, height)
# 假设容器宽度为800,超过则换行
if current_row_width > 800:
total_width = max(total_width, current_row_width - self._h_spacing)
rows += 1
current_row_width = width + self._h_spacing
current_row_height = height
total_width = max(total_width, current_row_width - self._h_spacing)
total_height = rows * current_row_height + (rows - 1) * self._v_spacing
return (total_width, total_height)
# 具体10:暗色主题实现
class DarkTheme(Theme):
"""暗色主题的具体实现"""
def __init__(self):
self._name = "Dark Theme"
self._colors = {
"primary": "#2E3440",
"secondary": "#3B4252",
"accent": "#88C0D0",
"text": "#ECEFF4",
"background": "#1E222A"
}
self._fonts = {
"title": {"family": "Arial", "size": 16, "weight": "bold"},
"body": {"family": "Segoe UI", "size": 14, "weight": "normal"},
"button": {"family": "Segoe UI", "size": 12, "weight": "medium"}
}
@property
def name(self) -> str:
return self._name
def get_color(self, color_type: str) -> str:
return self._colors.get(color_type, "#000000")
def get_font(self, font_type: str) -> dict:
return self._fonts.get(font_type, {"family": "Arial", "size": 12})
def get_padding(self, element_type: str) -> tuple[int, int, int, int]:
paddings = {
"window": (10, 10, 10, 10),
"button": (8, 16, 8, 16),
"textbox": (6, 10, 6, 10),
"label": (4, 8, 4, 8)
}
return paddings.get(element_type, (0, 0, 0, 0))
# 具体11:应用主类(使用抽象,依赖具体工厂)
class Application:
"""应用程序主类,依赖于抽象工厂"""
def __init__(self, factory: UIFactory, theme: Optional[Theme] = None):
self.factory = factory
self.theme = theme or DarkTheme()
self.window = None
self.controls = []
def create_ui(self) -> None:
# 使用抽象工厂创建组件
self.window = self.factory.create_window("我的应用")
# 创建控件
button = self.factory.create_button("点击我")
textbox = self.factory.create_textbox("请输入...")
label = self.factory.create_label("欢迎使用")
# 应用主题
if self.theme:
# 实际中这里会调用控件的apply_theme方法
print(f"应用主题: {self.theme.name}")
# 添加到控件列表
self.controls.extend([button, textbox, label])
# 设置布局
layout = self.factory.create_layout("flow")
for control in self.controls:
layout.add_control(control)
# 排列控件
layout.arrange((800, 600))
# 显示窗口
self.window.show()
# 输出UI信息
print("UI创建完成:")
for control in self.controls:
print(f" - {control.render()}")
def run(self) -> None:
"""运行应用主循环"""
print("应用启动...")
# 模拟事件循环
import time
for i in range(3):
print(f"主循环迭代 {i+1}")
time.sleep(1)
# 模拟事件
for control in self.controls:
if isinstance(control, Button):
# 模拟点击事件
event = UIEvent("click", x=50, y=50)
control.handle_event(event)
print("应用结束")
# 具体12:UI事件类
class UIEvent:
"""UI事件的具体实现"""
def __init__(self, type: str, **kwargs):
self.type = type
self.x = kwargs.get('x', 0)
self.y = kwargs.get('y', 0)
self.key = kwargs.get('key', '')
# 具体13:标签控件
class Label(UIControl):
"""标签控件的具体实现"""
def __init__(self, text: str, factory: UIFactory):
self._text = text
self._factory = factory
self._position = (0, 0)
self._size = (100, 20)
self._enabled = True
def render(self) -> str:
return f"标签: {self._text}"
def handle_event(self, event: UIEvent) -> bool:
# 标签通常不处理事件
return False
def set_enabled(self, enabled: bool) -> None:
self._enabled = enabled
@property
def position(self) -> tuple[int, int]:
return self._position
@position.setter
def position(self, value: tuple[int, int]) -> None:
self._position = value
@property
def size(self) -> tuple[int, int]:
return self._size
# 具体14:平台检测和工厂选择
def create_platform_factory() -> UIFactory:
"""根据当前平台创建具体的工厂"""
system = platform.system()
if system == "Windows":
return WindowsUIFactory()
elif system == "Darwin": # macOS
return MacUIFactory()
elif system == "Linux":
# 检查Linux桌面环境
desktop = os.environ.get("XDG_CURRENT_DESKTOP", "").lower()
if "gnome" in desktop or "kde" in desktop:
return LinuxUIFactory()
else:
return WindowsUIFactory() # 默认
else:
# 默认或Web
return WebUIFactory()
# 具体15:Web工厂实现
class WebUIFactory(UIFactory):
"""Web平台的具体工厂"""
def create_window(self, title: str) -> Window:
return WebWindow(title)
def create_button(self, text: str) -> Button:
button = Button(text, self)
button._size = (120, 36) # Web风格按钮
return button
def create_textbox(self, placeholder: str = "") -> TextBox:
textbox = TextBox(placeholder, self)
textbox._size = (250, 32) # Web风格文本框
return textbox
def create_label(self, text: str) -> Label:
return Label(text, self)
def create_layout(self, layout_type: str) -> LayoutManager:
if layout_type == "flex":
return FlexLayout()
else:
return FlowLayout()
# 具体16:Linux工厂实现
class LinuxUIFactory(UIFactory):
"""Linux平台的具体工厂"""
def create_window(self, title: str) -> Window:
return LinuxWindow(title)
def create_button(self, text: str) -> Button:
button = Button(text, self)
button._size = (110, 38) # Linux风格按钮
return button
def create_textbox(self, placeholder: str = "") -> TextBox:
textbox = TextBox(placeholder, self)
textbox._size = (230, 30) # Linux风格文本框
return textbox
def create_label(self, text: str) -> Label:
return Label(text, self)
def create_layout(self, layout_type: str) -> LayoutManager:
if layout_type == "flow":
return FlowLayout()
elif layout_type == "grid":
return GridLayout()
else:
return FlowLayout()
# 具体17:Flex布局实现
class FlexLayout(LayoutManager):
"""Flex布局的具体实现"""
def __init__(self, direction: str = "row"):
self._controls = []
self._direction = direction # "row" 或 "column"
self._spacing = 10
def add_control(self, control: UIControl) -> None:
self._controls.append(control)
def remove_control(self, control: UIControl) -> None:
if control in self._controls:
self._controls.remove(control)
def arrange(self, container_size: tuple[int, int]) -> None:
if self._direction == "row":
self._arrange_row(container_size)
else:
self._arrange_column(container_size)
def _arrange_row(self, container_size: tuple[int, int]):
x, y = 0, 0
for control in self._controls:
control.position = (x, y)
x += control.size[0] + self._spacing
def _arrange_column(self, container_size: tuple[int, int]):
x, y = 0, 0
for control in self._controls:
control.position = (x, y)
y += control.size[1] + self._spacing
def get_preferred_size(self) -> tuple[int, int]:
if not self._controls:
return (0, 0)
if self._direction == "row":
total_width = sum(control.size[0] for control in self._controls)
total_width += self._spacing * (len(self._controls) - 1)
max_height = max(control.size[1] for control in self._controls)
return (total_width, max_height)
else:
total_height = sum(control.size[1] for control in self._controls)
total_height += self._spacing * (len(self._controls) - 1)
max_width = max(control.size[0] for control in self._controls)
return (max_width, total_height)
# 具体18:网格布局实现
class GridLayout(LayoutManager):
"""网格布局的具体实现"""
def __init__(self, columns: int = 3):
self._controls = []
self._columns = columns
self._h_spacing = 10
self._v_spacing = 10
def add_control(self, control: UIControl) -> None:
self._controls.append(control)
def remove_control(self, control: UIControl) -> None:
if control in self._controls:
self._controls.remove(control)
def arrange(self, container_size: tuple[int, int]) -> None:
if not self._controls:
return
# 计算单元格大小
cell_width = (container_size[0] - (self._columns - 1) * self._h_spacing) // self._columns
cell_height = 60 # 固定高度
# 排列控件
for i, control in enumerate(self._controls):
row = i // self._columns
col = i % self._columns
x = col * (cell_width + self._h_spacing)
y = row * (cell_height + self._v_spacing)
control.position = (x, y)
control.size = (cell_width, cell_height)
def get_preferred_size(self) -> tuple[int, int]:
if not self._controls:
return (0, 0)
rows = (len(self._controls) + self._columns - 1) // self._columns
cell_width = 100 # 默认宽度
cell_height = 60 # 默认高度
width = self._columns * cell_width + (self._columns - 1) * self._h_spacing
height = rows * cell_height + (rows - 1) * self._v_spacing
return (width, height)
# 具体19:macOS特定布局
class MacFlowLayout(FlowLayout):
"""macOS风格的流式布局"""
def __init__(self):
super().__init__()
self._h_spacing = 15 # macOS有更大的间距
self._v_spacing = 15
# 具体20:macOS网格布局
class MacGridLayout(GridLayout):
"""macOS风格的网格布局"""
def __init__(self, columns: int = 3):
super().__init__(columns)
self._h_spacing = 15
self._v_spacing = 15
# 具体21:亮色主题实现
class LightTheme(Theme):
"""亮色主题的具体实现"""
def __init__(self):
self._name = "Light Theme"
self._colors = {
"primary": "#FFFFFF",
"secondary": "#F5F5F5",
"accent": "#007AFF",
"text": "#000000",
"background": "#F8F8F8"
}
self._fonts = {
"title": {"family": "San Francisco", "size": 17, "weight": "semibold"},
"body": {"family": "San Francisco", "size": 15, "weight": "regular"},
"button": {"family": "San Francisco", "size": 14, "weight": "medium"}
}
@property
def name(self) -> str:
return self._name
def get_color(self, color_type: str) -> str:
return self._colors.get(color_type, "#000000")
def get_font(self, font_type: str) -> dict:
return self._fonts.get(font_type, {"family": "Arial", "size": 12})
def get_padding(self, element_type: str) -> tuple[int, int, int, int]:
paddings = {
"window": (20, 20, 20, 20),
"button": (10, 20, 10, 20),
"textbox": (8, 12, 8, 12),
"label": (5, 10, 5, 10)
}
return paddings.get(element_type, (0, 0, 0, 0))
# 主程序入口
if __name__ == "__main__":
print("=== 跨平台UI框架示例 ===\n")
# 1. 创建具体工厂(根据当前平台)
factory = create_platform_factory()
print(f"平台: {platform.system()}, 使用工厂: {factory.__class__.__name__}")
# 2. 创建主题
theme = DarkTheme()
print(f"主题: {theme.name}")
# 3. 创建应用(依赖抽象工厂)
app = Application(factory, theme)
# 4. 创建UI
app.create_ui()
# 5. 运行应用
app.run()
# 6. 演示抽象与具体的分离
print("\n=== 抽象与具体分离示例 ===")
# 使用抽象接口编程
window: Window = factory.create_window("抽象窗口示例")
window.show()
window.set_title("新标题")
print(f"窗口标题: {window.title}, 是否可见: {window.is_visible}")
# 可以轻松切换具体实现
print("\n切换具体实现:")
windows_window = WindowsWindow("Windows窗口")
mac_window = MacWindow("macOS窗口")
web_window = WebWindow("Web窗口")
# 它们都遵循相同的抽象接口
windows = [windows_window, mac_window, web_window]
for w in windows:
w.show()
print(f" {w.__class__.__name__}: {w.title}")
# 演示多态
print("\n多态演示:")
button = factory.create_button("多态按钮")
textbox = factory.create_textbox("多态文本框")
controls: list[UIControl] = [button, textbox]
for control in controls:
print(f" 渲染: {control.render()}")
# 模拟事件
event = UIEvent("click", x=10, y=10)
control.handle_event(event)
// Java - 具体实现层:提供各平台的具体实现
package ui.framework.impl;
import ui.framework.*;
import java.awt.*;
// 具体1:Windows按钮实现
public class WindowsButton extends ObservableUIComponent implements Button {
private final String text;
private Position position;
private Size size;
private boolean enabled = true;
private Color backgroundColor = new Color(0, 120, 215); // Windows蓝色
public WindowsButton(String text) {
this.text = text;
this.size = new Size(100, 32);
}
@Override
public String render() {
return String.format("[Windows] 按钮: %s (位置: %s, 大小: %s)",
text, position, size);
}
@Override
public boolean handleEvent(UIEvent event) {
if ("click".equals(event.getType()) && enabled) {
System.out.println("Windows按钮被点击: " + text);
notifyObservers("click", event);
return true;
}
return false;
}
@Override
public String getComponentType() {
return "WindowsButton";
}
@Override
public Position getPosition() {
return position;
}
@Override
public void setPosition(Position position) {
this.position = position;
}
@Override
public Size getSize() {
return size;
}
@Override
public void setSize(Size size) {
this.size = size;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
// Windows特定方法
public void setWindowsStyle(WindowsButtonStyle style) {
// Windows特定的样式设置
}
}
// 具体2:macOS按钮实现
public class MacButton extends ObservableUIComponent implements Button {
private final String text;
private Position position;
private Size size;
private boolean enabled = true;
private Color backgroundColor = new Color(0, 122, 255); // macOS蓝色
public MacButton(String text) {
this.text = text;
this.size = new Size(120, 28);
}
@Override
public String render() {
return String.format("[macOS] 按钮: %s (位置: %s, 大小: %s)",
text, position, size);
}
@Override
public boolean handleEvent(UIEvent event) {
if ("click".equals(event.getType()) && enabled) {
System.out.println("macOS按钮被点击: " + text);
notifyObservers("click", event);
return true;
}
return false;
}
@Override
public String getComponentType() {
return "MacButton";
}
@Override
public Position getPosition() {
return position;
}
@Override
public void setPosition(Position position) {
this.position = position;
}
@Override
public Size getSize() {
return size;
}
@Override
public void setSize(Size size) {
this.size = size;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
// macOS特定方法
public void setMacStyle(MacButtonStyle style) {
// macOS特定的样式设置
}
}
// 具体3:Windows工厂实现
public class WindowsUIFactory extends UIFactory {
@Override
public Button createButton(String text) {
return new WindowsButton(text);
}
@Override
public TextField createTextField(String placeholder) {
return new WindowsTextField(placeholder);
}
@Override
public Label createLabel(String text) {
return new WindowsLabel(text);
}
@Override
public Window createWindow(String title) {
return new WindowsWindow(title);
}
@Override
public Panel createPanel() {
return new WindowsPanel();
}
@Override
protected Style getDefaultButtonStyle() {
return new WindowsStyle();
}
}
// 具体4:macOS工厂实现
public class MacUIFactory extends UIFactory {
@Override
public Button createButton(String text) {
return new MacButton(text);
}
@Override
public TextField createTextField(String placeholder) {
return new MacTextField(placeholder);
}
@Override
public Label createLabel(String text) {
return new MacLabel(text);
}
@Override
public Window createWindow(String title) {
return new MacWindow(title);
}
@Override
public Panel createPanel() {
return new MacPanel();
}
@Override
protected Style getDefaultButtonStyle() {
return new MacStyle();
}
}
// 具体5:暗色主题实现
public class DarkTheme extends Theme {
private final Color primaryColor = new Color(46, 52, 64); // #2E3440
private final Color secondaryColor = new Color(59, 66, 82); // #3B4252
private final Color accentColor = new Color(136, 192, 208); // #88C0D0
private final Color textColor = new Color(236, 239, 244); // #ECEFF4
private final Color backgroundColor = new Color(30, 34, 42); // #1E222A
public DarkTheme() {
super("Dark Theme");
}
@Override
public Color getPrimaryColor() {
return primaryColor;
}
@Override
public Color getSecondaryColor() {
return secondaryColor;
}
@Override
public Color getTextColor() {
return textColor;
}
@Override
public Color getBackgroundColor() {
return backgroundColor;
}
@Override
public Font getTitleFont() {
return new Font("Arial", Font.BOLD, 16);
}
@Override
public Font getBodyFont() {
return new Font("Segoe UI", Font.PLAIN, 14);
}
@Override
public Font getButtonFont() {
return new Font("Segoe UI", Font.BOLD, 12);
}
@Override
public Style createStyle(String styleName) {
return new DarkStyle(styleName, this);
}
}
// 具体6:亮色主题实现
public class LightTheme extends Theme {
private final Color primaryColor = new Color(255, 255, 255); // #FFFFFF
private final Color secondaryColor = new Color(245, 245, 245); // #F5F5F5
private final Color accentColor = new Color(0, 122, 255); // #007AFF
private final Color textColor = new Color(0, 0, 0); // #000000
private final Color backgroundColor = new Color(248, 248, 248); // #F8F8F8
public LightTheme() {
super("Light Theme");
}
@Override
public Color getPrimaryColor() {
return primaryColor;
}
@Override
public Color getSecondaryColor() {
return secondaryColor;
}
@Override
public Color getTextColor() {
return textColor;
}
@Override
public Color getBackgroundColor() {
return backgroundColor;
}
@Override
public Font getTitleFont() {
return new Font("San Francisco", Font.BOLD, 17);
}
@Override
public Font getBodyFont() {
return new Font("San Francisco", Font.PLAIN, 15);
}
@Override
public Font getButtonFont() {
return new Font("San Francisco", Font.BOLD, 14);
}
@Override
public Style createStyle(String styleName) {
return new LightStyle(styleName, this);
}
}
// 具体7:应用类
public class Application {
private final UIFactory factory;
private final Theme theme;
private Window mainWindow;
private List<UIComponent> components = new ArrayList<>();
public Application(UIFactory factory, Theme theme) {
this.factory = factory;
this.theme = theme;
}
public void createUI() {
// 使用抽象工厂创建组件
mainWindow = factory.createWindow("我的应用");
// 创建按钮
Button button = factory.createDefaultButton("点击我");
components.add(button);
// 创建文本框
TextField textField = factory.createTextField("请输入...");
components.add(textField);
// 创建标签
Label label = factory.createLabel("欢迎使用");
components.add(label);
// 应用主题
for (UIComponent component : components) {
theme.applyTo(component);
}
System.out.println("UI创建完成:");
for (UIComponent component : components) {
System.out.println(" - " + component.render());
}
}
public void run() {
System.out.println("应用启动...");
// 模拟事件循环
for (int i = 0; i < 3; i++) {
System.out.println("主循环迭代 " + (i + 1));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 模拟事件
for (UIComponent component : components) {
if (component instanceof Button) {
UIEvent event = new UIEvent("click", 50, 50);
component.handleEvent(event);
}
}
}
System.out.println("应用结束");
}
}
// 具体8:平台检测
public class PlatformDetector {
public static UIFactory createPlatformFactory() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
return new WindowsUIFactory();
} else if (osName.contains("mac")) {
return new MacUIFactory();
} else if (osName.contains("nix") || osName.contains("nux")) {
// 检测Linux桌面环境
String desktop = System.getenv("XDG_CURRENT_DESKTOP");
if (desktop != null && (desktop.toLowerCase().contains("gnome") ||
desktop.toLowerCase().contains("kde"))) {
return new LinuxUIFactory();
} else {
return new WindowsUIFactory(); // 默认
}
} else {
return new WebUIFactory(); // 默认Web
}
}
}
// 具体9:Linux工厂实现
public class LinuxUIFactory extends UIFactory {
@Override
public Button createButton(String text) {
return new LinuxButton(text);
}
@Override
public TextField createTextField(String placeholder) {
return new LinuxTextField(placeholder);
}
@Override
public Label createLabel(String text) {
return new LinuxLabel(text);
}
@Override
public Window createWindow(String title) {
return new LinuxWindow(title);
}
@Override
public Panel createPanel() {
return new LinuxPanel();
}
@Override
protected Style getDefaultButtonStyle() {
return new LinuxStyle();
}
}
// 具体10:Web工厂实现
public class WebUIFactory extends UIFactory {
@Override
public Button createButton(String text) {
return new WebButton(text);
}
@Override
public TextField createTextField(String placeholder) {
return new WebTextField(placeholder);
}
@Override
public Label createLabel(String text) {
return new WebLabel(text);
}
@Override
public Window createWindow(String title) {
return new WebWindow(title);
}
@Override
public Panel createPanel() {
return new WebPanel();
}
@Override
protected Style getDefaultButtonStyle() {
return new WebStyle();
}
}
// 主程序
public class Main {
public static void main(String[] args) {
System.out.println("=== 跨平台UI框架示例 ===\n");
// 1. 创建具体工厂
UIFactory factory = PlatformDetector.createPlatformFactory();
System.out.println("平台: " + System.getProperty("os.name"));
System.out.println("使用工厂: " + factory.getClass().getSimpleName());
// 2. 创建主题
Theme theme = new DarkTheme();
System.out.println("主题: " + theme.getName());
// 3. 创建应用
Application app = new Application(factory, theme);
// 4. 创建UI
app.createUI();
// 5. 运行应用
app.run();
// 6. 演示抽象与具体的分离
System.out.println("\n=== 抽象与具体分离示例 ===");
// 使用抽象接口编程
Window window = factory.createWindow("抽象窗口示例");
window.show();
System.out.println("窗口标题: " + window.getTitle());
// 可以轻松切换具体实现
System.out.println("\n切换具体实现:");
Window windowsWindow = new WindowsWindow("Windows窗口");
Window macWindow = new MacWindow("macOS窗口");
Window webWindow = new WebWindow("Web窗口");
Window[] windows = {windowsWindow, macWindow, webWindow};
for (Window w : windows) {
w.show();
System.out.println(" " + w.getClass().getSimpleName() + ": " + w.getTitle());
}
}
}
// C++ - 具体实现层:提供各平台的具体实现
#include <iostream>
#include <string>
#include <memory>
#include <vector>
// 具体1:Windows按钮实现
class WindowsButton : public UIComponent, public Drawable {
private:
std::string text_;
Point position_;
Size size_;
bool enabled_;
std::string backgroundColor_;
public:
WindowsButton(const std::string& text)
: text_(text), enabled_(true), backgroundColor_("#0078D4") {
size_ = {100, 32};
}
void render() const override {
std::cout << "[Windows] 按钮: " << text_
<< " (位置: " << position_.x << "," << position_.y
<< ", 大小: " << size_.width << "x" << size_.height
<< ")" << std::endl;
}
bool handleEvent(const std::string& eventType, void* eventData) override {
if (eventType == "click" && enabled_) {
std::cout << "Windows按钮被点击: " << text_ << std::endl;
return true;
}
return false;
}
std::string getType() const override {
return "WindowsButton";
}
Point getPosition() const override {
return position_;
}
void setPosition(Point position) override {
position_ = position;
}
Size getSize() const override {
return size_;
}
void setSize(Size size) override {
size_ = size;
}
void draw() const override {
std::cout << "绘制Windows按钮: " << text_
<< " 背景色: " << backgroundColor_ << std::endl;
}
// Windows特定方法
void setWindowsStyle(const WindowsButtonStyle& style) {
// Windows特定的样式设置
}
};
// 具体2:macOS按钮实现
class MacButton : public UIComponent, public Drawable {
private:
std::string text_;
Point position_;
Size size_;
bool enabled_;
std::string backgroundColor_;
public:
MacButton(const std::string& text)
: text_(text), enabled_(true), backgroundColor_("#007AFF") {
size_ = {120, 28};
}
void render() const override {
std::cout << "[macOS] 按钮: " << text_
<< " (位置: " << position_.x << "," << position_.y
<< ", 大小: " << size_.width << "x" << size_.height
<< ")" << std::endl;
}
bool handleEvent(const std::string& eventType, void* eventData) override {
if (eventType == "click" && enabled_) {
std::cout << "macOS按钮被点击: " << text_ << std::endl;
return true;
}
return false;
}
std::string getType() const override {
return "MacButton";
}
Point getPosition() const override {
return position_;
}
void setPosition(Point position) override {
position_ = position;
}
Size getSize() const override {
return size_;
}
void setSize(Size size) override {
size_ = size;
}
void draw() const override {
std::cout << "绘制macOS按钮: " << text_
<< " 背景色: " << backgroundColor_ << std::endl;
}
// macOS特定方法
void setMacStyle(const MacButtonStyle& style) {
// macOS特定的样式设置
}
};
// 具体3:Windows工厂实现
class WindowsUIFactory : public UIFactory<UIComponent> {
public:
std::unique_ptr<UIComponent> createComponent(const std::string& name) override {
if (name.find("button") != std::string::npos) {
return std::make_unique<WindowsButton>(name);
} else if (name.find("textbox") != std::string::npos) {
return std::make_unique<WindowsTextBox>(name);
} else if (name.find("label") != std::string::npos) {
return std::make_unique<WindowsLabel>(name);
}
return nullptr;
}
protected:
void initializeComponent(UIComponent* component) override {
// Windows特定的初始化
component->setSize({100, 50});
}
void applyDefaultStyle(UIComponent* component) override {
// Windows默认样式
}
};
// 具体4:macOS工厂实现
class MacUIFactory : public UIFactory<UIComponent> {
public:
std::unique_ptr<UIComponent> createComponent(const std::string& name) override {
if (name.find("button") != std::string::npos) {
return std::make_unique<MacButton>(name);
} else if (name.find("textbox") != std::string::npos) {
return std::make_unique<MacTextBox>(name);
} else if (name.find("label") != std::string::npos) {
return std::make_unique<MacLabel>(name);
}
return nullptr;
}
protected:
void initializeComponent(UIComponent* component) override {
// macOS特定的初始化
component->setSize({120, 35});
}
void applyDefaultStyle(UIComponent* component) override {
// macOS默认样式
}
};
// 具体5:暗色主题实现
class DarkTheme : public Theme {
private:
std::map<std::string, std::string> colors_;
public:
DarkTheme() {
colors_["primary"] = "#2E3440";
colors_["secondary"] = "#3B4252";
colors_["accent"] = "#88C0D0";
colors_["text"] = "#ECEFF4";
colors_["background"] = "#1E222A";
}
std::string getColor(const std::string& colorName) const override {
auto it = colors_.find(colorName);
if (it != colors_.end()) {
return it->second;
}
return "#000000";
}
std::string getFont(const std::string& fontName) const override {
if (fontName == "title") {
return "Arial, 16px, bold";
} else if (fontName == "body") {
return "Segoe UI, 14px";
} else if (fontName == "button") {
return "Segoe UI, 12px, medium";
}
return "Arial, 12px";
}
int getSpacing(const std::string& spacingType) const override {
if (spacingType == "small") return 4;
if (spacingType == "medium") return 8;
if (spacingType == "large") return 16;
return 0;
}
protected:
void applyColors(UIComponent* component) const override {
std::cout << "应用暗色主题颜色到: " << component->getType() << std::endl;
}
void applyFonts(UIComponent* component) const override {
std::cout << "应用暗色主题字体到: " << component->getType() << std::endl;
}
void applySpacing(UIComponent* component) const override {
std::cout << "应用暗色主题间距到: " << component->getType() << std::endl;
}
};
// 具体6:亮色主题实现
class LightTheme : public Theme {
private:
std::map<std::string, std::string> colors_;
public:
LightTheme() {
colors_["primary"] = "#FFFFFF";
colors_["secondary"] = "#F5F5F5";
colors_["accent"] = "#007AFF";
colors_["text"] = "#000000";
colors_["background"] = "#F8F8F8";
}
std::string getColor(const std::string& colorName) const override {
auto it = colors_.find(colorName);
if (it != colors_.end()) {
return it->second;
}
return "#000000";
}
std::string getFont(const std::string& fontName) const override {
if (fontName == "title") {
return "San Francisco, 17px, semibold";
} else if (fontName == "body") {
return "San Francisco, 15px";
} else if (fontName == "button") {
return "San Francisco, 14px, medium";
}
return "Arial, 12px";
}
int getSpacing(const std::string& spacingType) const override {
if (spacingType == "small") return 6;
if (spacingType == "medium") return 12;
if (spacingType == "large") return 24;
return 0;
}
protected:
void applyColors(UIComponent* component) const override {
std::cout << "应用亮色主题颜色到: " << component->getType() << std::endl;
}
void applyFonts(UIComponent* component) const override {
std::cout << "应用亮色主题字体到: " << component->getType() << std::endl;
}
void applySpacing(UIComponent* component) const override {
std::cout << "应用亮色主题间距到: " << component->getType() << std::endl;
}
};
// 具体7:流式布局实现
class FlowLayout : public LayoutStrategy {
public:
void applyLayout(std::vector<UIComponent*>& components,
const UIComponent::Size& containerSize) override {
int x = 0, y = 0;
int maxRowHeight = 0;
int hSpacing = 10;
int vSpacing = 10;
for (auto* component : components) {
auto size = component->getSize();
// 检查是否需要换行
if (x + size.width > containerSize.width) {
x = 0;
y += maxRowHeight + vSpacing;
maxRowHeight = 0;
}
// 设置控件位置
component->setPosition({x, y});
// 更新位置和行高
x += size.width + hSpacing;
maxRowHeight = std::max(maxRowHeight, size.height);
}
}
UIComponent::Size calculatePreferredSize(
const std::vector<UIComponent*>& components) override {
if (components.empty()) {
return {0, 0};
}
int totalWidth = 0;
int maxHeight = 0;
int currentRowWidth = 0;
int currentRowHeight = 0;
int rows = 1;
int hSpacing = 10;
int vSpacing = 10;
for (auto* component : components) {
auto size = component->getSize();
currentRowWidth += size.width + hSpacing;
currentRowHeight = std::max(currentRowHeight, size.height);
// 假设容器宽度为800,超过则换行
if (currentRowWidth > 800) {
totalWidth = std::max(totalWidth, currentRowWidth - hSpacing);
rows++;
currentRowWidth = size.width + hSpacing;
currentRowHeight = size.height;
}
}
totalWidth = std::max(totalWidth, currentRowWidth - hSpacing);
int totalHeight = rows * currentRowHeight + (rows - 1) * vSpacing;
return {totalWidth, totalHeight};
}
std::string getName() const override {
return "FlowLayout";
}
};
// 具体8:应用类
class Application {
private:
std::unique_ptr<UIFactory<UIComponent>> factory_;
std::unique_ptr<Theme> theme_;
std::vector<std::unique_ptr<UIComponent>> components_;
public:
Application(std::unique_ptr<UIFactory<UIComponent>> factory,
std::unique_ptr<Theme> theme)
: factory_(std::move(factory)), theme_(std::move(theme)) {}
void createUI() {
// 使用抽象工厂创建组件
auto button = factory_->create("myButton");
auto textbox = factory_->create("myTextbox");
auto label = factory_->create("myLabel");
if (button) components_.push_back(std::move(button));
if (textbox) components_.push_back(std::move(textbox));
if (label) components_.push_back(std::move(label));
// 应用主题
if (theme_) {
for (const auto& component : components_) {
theme_->applyTo(component.get());
}
}
std::cout << "UI创建完成:" << std::endl;
for (const auto& component : components_) {
component->render();
}
}
void run() {
std::cout << "应用启动..." << std::endl;
// 模拟事件循环
for (int i = 0; i < 3; ++i) {
std::cout << "主循环迭代 " << (i + 1) << std::endl;
// 模拟事件
for (const auto& component : components_) {
component->handleEvent("click", nullptr);
}
// 模拟延时
// std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "应用结束" << std::endl;
}
};
// 具体9:平台检测
#ifdef _WIN32
#define PLATFORM_WINDOWS 1
#elif __APPLE__
#define PLATFORM_MAC 1
#elif __linux__
#define PLATFORM_LINUX 1
#else
#define PLATFORM_WEB 1
#endif
std::unique_ptr<UIFactory<UIComponent>> createPlatformFactory() {
#ifdef PLATFORM_WINDOWS
return std::make_unique<WindowsUIFactory>();
#elif defined(PLATFORM_MAC)
return std::make_unique<MacUIFactory>();
#elif defined(PLATFORM_LINUX)
return std::make_unique<LinuxUIFactory>();
#else
return std::make_unique<WebUIFactory>();
#endif
}
// 主程序
int main() {
std::cout << "=== 跨平台UI框架示例 ===" << std::endl << std::endl;
// 1. 创建具体工厂
auto factory = createPlatformFactory();
#ifdef PLATFORM_WINDOWS
std::cout << "平台: Windows" << std::endl;
#elif defined(PLATFORM_MAC)
std::cout << "平台: macOS" << std::endl;
#elif defined(PLATFORM_LINUX)
std::cout << "平台: Linux" << std::endl;
#else
std::cout << "平台: Web" << std::endl;
#endif
std::cout << "使用工厂: " << typeid(*factory).name() << std::endl;
// 2. 创建主题
auto theme = std::make_unique<DarkTheme>();
std::cout << "主题: Dark Theme" << std::endl;
// 3. 创建应用
Application app(std::move(factory), std::move(theme));
// 4. 创建UI
app.createUI();
// 5. 运行应用
app.run();
// 6. 演示抽象与具体的分离
std::cout << std::endl << "=== 抽象与具体分离示例 ===" << std::endl;
// 使用抽象接口编程
auto buttonFactory = std::make_unique<WindowsUIFactory>();
auto button = buttonFactory->create("抽象按钮");
if (button) {
button->render();
}
// 可以轻松切换具体实现
std::cout << std::endl << "切换具体实现:" << std::endl;
WindowsButton windowsButton("Windows按钮");
MacButton macButton("macOS按钮");
std::vector<UIComponent*> buttons = {&windowsButton, &macButton};
for (auto* btn : buttons) {
btn->render();
}
return 0;
}
第三阶段:抽象与具体的综合应用
# Python - 抽象与具体的综合应用:插件系统
"""
综合应用:抽象定义插件接口,具体实现各种插件
"""
# 抽象1:插件接口
from abc import ABC, abstractmethod
from typing import Dict, Any, List, Optional
import json
class Plugin(ABC):
"""插件抽象:定义所有插件必须实现的接口"""
@property
@abstractmethod
def name(self) -> str:
"""插件名称"""
pass
@property
@abstractmethod
def version(self) -> str:
"""插件版本"""
pass
@property
@abstractmethod
def description(self) -> str:
"""插件描述"""
pass
@abstractmethod
def initialize(self, context: 'PluginContext') -> bool:
"""初始化插件"""
pass
@abstractmethod
def shutdown(self) -> None:
"""关闭插件"""
pass
@abstractmethod
def execute(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""执行插件主要功能"""
pass
@abstractmethod
def get_config_schema(self) -> Dict[str, Any]:
"""获取配置模式"""
pass
@abstractmethod
def validate_config(self, config: Dict[str, Any]) -> bool:
"""验证配置"""
pass
# 抽象2:插件上下文
class PluginContext(ABC):
"""插件上下文抽象:插件与主程序交互的接口"""
@abstractmethod
def log(self, level: str, message: str) -> None:
"""记录日志"""
pass
@abstractmethod
def get_resource(self, resource_type: str, resource_id: str) -> Any:
"""获取资源"""
pass
@abstractmethod
def notify_event(self, event_type: str, data: Dict[str, Any]) -> None:
"""通知事件"""
pass
@abstractmethod
def register_service(self, service_name: str, service: Any) -> None:
"""注册服务"""
pass
@abstractmethod
def get_service(self, service_name: str) -> Any:
"""获取服务"""
pass
# 抽象3:插件管理器
class PluginManager(ABC):
"""插件管理器抽象:管理插件的生命周期"""
@abstractmethod
def load_plugin(self, plugin_path: str) -> bool:
"""加载插件"""
pass
@abstractmethod
def unload_plugin(self, plugin_name: str) -> bool:
"""卸载插件"""
pass
@abstractmethod
def get_plugin(self, plugin_name: str) -> Optional[Plugin]:
"""获取插件"""
pass
@abstractmethod
def list_plugins(self) -> List[str]:
"""列出所有插件"""
pass
@abstractmethod
def execute_plugin(self, plugin_name: str, data: Dict[str, Any]) -> Dict[str, Any]:
"""执行插件"""
pass
@abstractmethod
def register_plugin_factory(self, plugin_type: str, factory: 'PluginFactory') -> None:
"""注册插件工厂"""
pass
# 抽象4:插件工厂
class PluginFactory(ABC):
"""插件工厂抽象:创建插件实例"""
@abstractmethod
def create_plugin(self, config: Dict[str, Any]) -> Plugin:
"""创建插件"""
pass
@abstractmethod
def get_supported_types(self) -> List[str]:
"""获取支持的插件类型"""
pass
# ================ 具体实现层 ================
# 具体1:数据验证插件
class DataValidationPlugin(Plugin):
"""数据验证插件的具体实现"""
def __init__(self):
self._name = "DataValidator"
self._version = "1.0.0"
self._description = "数据验证插件,支持多种验证规则"
self._context = None
self._validation_rules = []
@property
def name(self) -> str:
return self._name
@property
def version(self) -> str:
return self._version
@property
def description(self) -> str:
return self._description
def initialize(self, context: PluginContext) -> bool:
self._context = context
self._context.log("INFO", f"初始化插件: {self.name}")
# 加载验证规则
self._load_validation_rules()
# 注册验证服务
self._context.register_service("data_validator", self)
return True
def shutdown(self) -> None:
self._context.log("INFO", f"关闭插件: {self.name}")
self._validation_rules.clear()
def execute(self, data: Dict[str, Any]) -> Dict[str, Any]:
validation_results = []
for field, value in data.items():
for rule in self._validation_rules:
if rule["field"] == field or rule["field"] == "*":
is_valid, message = self._apply_rule(rule, value)
validation_results.append({
"field": field,
"value": value,
"rule": rule["name"],
"valid": is_valid,
"message": message
})
return {
"valid": all(r["valid"] for r in validation_results),
"results": validation_results
}
def get_config_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"strict_mode": {"type": "boolean", "default": False},
"validation_rules": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {"type": "string"},
"type": {"type": "string"},
"required": {"type": "boolean"},
"min": {"type": "number"},
"max": {"type": "number"},
"pattern": {"type": "string"}
}
}
}
}
}
def validate_config(self, config: Dict[str, Any]) -> bool:
try:
# 简单的配置验证
if "validation_rules" in config:
if not isinstance(config["validation_rules"], list):
return False
for rule in config["validation_rules"]:
if "field" not in rule or "type" not in rule:
return False
return True
except Exception:
return False
def _load_validation_rules(self) -> None:
# 加载默认验证规则
self._validation_rules = [
{"field": "email", "name": "EmailValidation", "type": "email"},
{"field": "password", "name": "PasswordValidation", "type": "password", "min_length": 8},
{"field": "age", "name": "AgeValidation", "type": "number", "min": 0, "max": 150},
{"field": "*", "name": "RequiredValidation", "type": "required"}
]
def _apply_rule(self, rule: Dict[str, Any], value: Any) -> tuple[bool, str]:
rule_type = rule.get("type")
if rule_type == "required":
if value is None or (isinstance(value, str) and value.strip() == ""):
return False, "该字段是必填项"
return True, ""
elif rule_type == "email":
if not isinstance(value, str):
return False, "邮箱必须是字符串"
if "@" not in value or "." not in value:
return False, "邮箱格式不正确"
return True, ""
elif rule_type == "password":
if not isinstance(value, str):
return False, "密码必须是字符串"
if len(value) < rule.get("min_length", 6):
return False, f"密码长度不能少于{rule['min_length']}位"
return True, ""
elif rule_type == "number":
try:
num = float(value)
if "min" in rule and num < rule["min"]:
return False, f"不能小于{rule['min']}"
if "max" in rule and num > rule["max"]:
return False, f"不能大于{rule['max']}"
return True, ""
except ValueError:
return False, "必须是数字"
return True, ""
# 具体2:数据转换插件
class DataTransformationPlugin(Plugin):
"""数据转换插件的具体实现"""
def __init__(self):
self._name = "DataTransformer"
self._version = "1.0.0"
self._description = "数据转换插件,支持多种数据格式转换"
self._context = None
self._transformations = {}
@property
def name(self) -> str:
return self._name
@property
def version(self) -> str:
return self._version
@property
def description(self) -> str:
return self._description
def initialize(self, context: PluginContext) -> bool:
self._context = context
self._context.log("INFO", f"初始化插件: {self.name}")
# 注册转换函数
self._register_transformations()
# 注册转换服务
self._context.register_service("data_transformer", self)
return True
def shutdown(self) -> None:
self._context.log("INFO", f"关闭插件: {self.name}")
self._transformations.clear()
def execute(self, data: Dict[str, Any]) -> Dict[str, Any]:
result = {}
for key, value in data.items():
# 应用所有适用的转换
transformed = value
for transform_name, transform_func in self._transformations.items():
if transform_name.startswith("transform_"):
transformed = transform_func(transformed)
result[key] = transformed
return {"transformed_data": result}
def get_config_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"transformations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"type": {"type": "string"},
"params": {"type": "object"}
}
}
}
}
}
def validate_config(self, config: Dict[str, Any]) -> bool:
return True
def _register_transformations(self) -> None:
"""注册具体的转换函数"""
self._transformations = {
"transform_to_uppercase": lambda x: str(x).upper() if isinstance(x, str) else x,
"transform_to_lowercase": lambda x: str(x).lower() if isinstance(x, str) else x,
"transform_trim": lambda x: str(x).strip() if isinstance(x, str) else x,
"transform_to_json": lambda x: json.dumps(x) if isinstance(x, (dict, list)) else str(x),
"transform_from_json": lambda x: json.loads(x) if isinstance(x, str) else x,
"transform_numeric": lambda x: float(x) if isinstance(x, (int, float, str)) else x
}
# 具体3:文件处理插件
class FileProcessingPlugin(Plugin):
"""文件处理插件的具体实现"""
def __init__(self):
self._name = "FileProcessor"
self._version = "1.0.0"
self._description = "文件处理插件,支持多种文件格式"
self._context = None
self._supported_formats = ["txt", "csv", "json", "xml"]
@property
def name(self) -> str:
return self._name
@property
def version(self) -> str:
return self._version
@property
def description(self) -> str:
return self._description
def initialize(self, context: PluginContext) -> bool:
self._context = context
self._context.log("INFO", f"初始化插件: {self.name}")
# 注册文件处理服务
self._context.register_service("file_processor", self)
return True
def shutdown(self) -> None:
self._context.log("INFO", f"关闭插件: {self.name}")
def execute(self, data: Dict[str, Any]) -> Dict[str, Any]:
file_path = data.get("file_path")
operation = data.get("operation", "read")
if operation == "read":
content = self._read_file(file_path)
return {"content": content, "format": self._detect_format(file_path)}
elif operation == "write":
content = data.get("content", "")
self._write_file(file_path, content)
return {"success": True, "message": "文件写入成功"}
elif operation == "convert":
source_format = data.get("source_format")
target_format = data.get("target_format")
content = data.get("content", "")
converted = self._convert_format(content, source_format, target_format)
return {"converted_content": converted, "target_format": target_format}
return {"error": "不支持的操作"}
def get_config_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"default_encoding": {"type": "string", "default": "utf-8"},
"max_file_size": {"type": "number", "default": 10485760}, # 10MB
"supported_formats": {
"type": "array",
"items": {"type": "string"}
}
}
}
def validate_config(self, config: Dict[str, Any]) -> bool:
if "max_file_size" in config:
if not isinstance(config["max_file_size"], (int, float)):
return False
if config["max_file_size"] <= 0:
return False
return True
def _read_file(self, file_path: str) -> str:
"""具体的文件读取实现"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
except Exception as e:
self._context.log("ERROR", f"读取文件失败: {e}")
return ""
def _write_file(self, file_path: str, content: str) -> bool:
"""具体的文件写入实现"""
try:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
return True
except Exception as e:
self._context.log("ERROR", f"写入文件失败: {e}")
return False
def _detect_format(self, file_path: str) -> str:
"""检测文件格式的具体实现"""
if file_path.endswith('.txt'):
return 'txt'
elif file_path.endswith('.csv'):
return 'csv'
elif file_path.endswith('.json'):
return 'json'
elif file_path.endswith('.xml'):
return 'xml'
else:
return 'unknown'
def _convert_format(self, content: str, source_format: str, target_format: str) -> str:
"""格式转换的具体实现"""
if source_format == "json" and target_format == "csv":
return self._json_to_csv(content)
elif source_format == "csv" and target_format == "json":
return self._csv_to_json(content)
else:
return content
def _json_to_csv(self, json_content: str) -> str:
"""JSON转CSV的具体实现"""
try:
data = json.loads(json_content)
if isinstance(data, list) and data:
# 提取表头
headers = list(data[0].keys())
csv_lines = [','.join(headers)]
# 提取数据行
for item in data:
row = [str(item.get(h, '')) for h in headers]
csv_lines.append(','.join(row))
return '\n'.join(csv_lines)
except Exception as e:
self._context.log("ERROR", f"JSON转CSV失败: {e}")
return json_content
def _csv_to_json(self, csv_content: str) -> str:
"""CSV转JSON的具体实现"""
lines = csv_content.strip().split('\n')
if len(lines) < 2:
return '[]'
headers = lines[0].split(',')
result = []
for line in lines[1:]:
values = line.split(',')
if len(values) == len(headers):
item = {headers[i]: values[i] for i in range(len(headers))}
result.append(item)
return json.dumps(result, ensure_ascii=False, indent=2)
# 具体4:插件管理器实现
class DefaultPluginManager(PluginManager):
"""插件管理器的具体实现"""
def __init__(self):
self._plugins: Dict[str, Plugin] = {}
self._context = DefaultPluginContext()
self._factories: Dict[str, PluginFactory] = {}
# 注册默认工厂
self.register_plugin_factory("validation", ValidationPluginFactory())
self.register_plugin_factory("transformation", TransformationPluginFactory())
self.register_plugin_factory("file_processing", FileProcessingPluginFactory())
def load_plugin(self, plugin_path: str) -> bool:
try:
# 动态加载插件(简化版)
plugin_type = self._detect_plugin_type(plugin_path)
if plugin_type in self._factories:
# 加载配置
config = self._load_config(plugin_path)
# 创建插件
factory = self._factories[plugin_type]
plugin = factory.create_plugin(config)
# 初始化插件
if plugin.initialize(self._context):
self._plugins[plugin.name] = plugin
self._context.log("INFO", f"加载插件成功: {plugin.name}")
return True
else:
self._context.log("ERROR", f"初始化插件失败: {plugin_path}")
return False
else:
self._context.log("ERROR", f"未知的插件类型: {plugin_type}")
return False
except Exception as e:
self._context.log("ERROR", f"加载插件失败: {e}")
return False
def unload_plugin(self, plugin_name: str) -> bool:
if plugin_name in self._plugins:
plugin = self._plugins[plugin_name]
plugin.shutdown()
del self._plugins[plugin_name]
self._context.log("INFO", f"卸载插件成功: {plugin_name}")
return True
return False
def get_plugin(self, plugin_name: str) -> Optional[Plugin]:
return self._plugins.get(plugin_name)
def list_plugins(self) -> List[str]:
return list(self._plugins.keys())
def execute_plugin(self, plugin_name: str, data: Dict[str, Any]) -> Dict[str, Any]:
plugin = self.get_plugin(plugin_name)
if plugin:
return plugin.execute(data)
else:
return {"error": f"插件不存在: {plugin_name}"}
def register_plugin_factory(self, plugin_type: str, factory: PluginFactory) -> None:
self._factories[plugin_type] = factory
self._context.log("INFO", f"注册插件工厂: {plugin_type}")
def _detect_plugin_type(self, plugin_path: str) -> str:
"""检测插件类型的具体实现"""
if "validator" in plugin_path.lower():
return "validation"
elif "transformer" in plugin_path.lower():
return "transformation"
elif "file" in plugin_path.lower():
return "file_processing"
else:
return "unknown"
def _load_config(self, plugin_path: str) -> Dict[str, Any]:
"""加载配置的具体实现"""
# 简化实现,实际中会从文件读取
return {}
# 具体5:插件上下文实现
class DefaultPluginContext(PluginContext):
"""插件上下文的具体实现"""
def __init__(self):
self._services: Dict[str, Any] = {}
self._log_handler = PrintLogHandler()
def log(self, level: str, message: str) -> None:
self._log_handler.log(level, message)
def get_resource(self, resource_type: str, resource_id: str) -> Any:
# 简化实现
return None
def notify_event(self, event_type: str, data: Dict[str, Any]) -> None:
print(f"事件通知 [{event_type}]: {data}")
def register_service(self, service_name: str, service: Any) -> None:
self._services[service_name] = service
def get_service(self, service_name: str) -> Any:
return self._services.get(service_name)
# 具体6:日志处理器
class PrintLogHandler:
"""简单的日志处理器实现"""
def log(self, level: str, message: str) -> None:
print(f"[{level.upper()}] {message}")
# 具体7:验证插件工厂
class ValidationPluginFactory(PluginFactory):
"""验证插件工厂的具体实现"""
def create_plugin(self, config: Dict[str, Any]) -> Plugin:
plugin = DataValidationPlugin()
# 应用配置
return plugin
def get_supported_types(self) -> List[str]:
return ["validation", "validator", "data_validation"]
# 具体8:转换插件工厂
class TransformationPluginFactory(PluginFactory):
"""转换插件工厂的具体实现"""
def create_plugin(self, config: Dict[str, Any]) -> Plugin:
plugin = DataTransformationPlugin()
# 应用配置
return plugin
def get_supported_types(self) -> List[str]:
return ["transformation", "transformer", "data_transformation"]
# 具体9:文件处理插件工厂
class FileProcessingPluginFactory(PluginFactory):
"""文件处理插件工厂的具体实现"""
def create_plugin(self, config: Dict[str, Any]) -> Plugin:
plugin = FileProcessingPlugin()
# 应用配置
return plugin
def get_supported_types(self) -> List[str]:
return ["file_processing", "file_processor", "file_handler"]
# 主程序:演示抽象与具体的综合应用
def main():
print("=== 插件系统示例:抽象与具体的综合应用 ===\n")
# 1. 创建插件管理器
plugin_manager = DefaultPluginManager()
# 2. 加载插件
print("加载插件...")
plugin_manager.load_plugin("data_validator")
plugin_manager.load_plugin("data_transformer")
plugin_manager.load_plugin("file_processor")
# 3. 列出已加载的插件
print("\n已加载的插件:")
for plugin_name in plugin_manager.list_plugins():
plugin = plugin_manager.get_plugin(plugin_name)
print(f" - {plugin_name} (版本: {plugin.version}): {plugin.description}")
# 4. 执行数据验证插件
print("\n执行数据验证插件:")
test_data = {
"email": "user@example.com",
"password": "password123",
"age": 25,
"name": "John Doe"
}
validation_result = plugin_manager.execute_plugin("DataValidator", test_data)
print(f"验证结果: {validation_result['valid']}")
for result in validation_result["results"]:
status = "✓" if result["valid"] else "✗"
print(f" {status} {result['field']}: {result['message']}")
# 5. 执行数据转换插件
print("\n执行数据转换插件:")
transformation_result = plugin_manager.execute_plugin("DataTransformer", test_data)
print(f"转换结果: {transformation_result['transformed_data']}")
# 6. 执行文件处理插件
print("\n执行文件处理插件:")
file_data = {
"file_path": "test.txt",
"operation": "write",
"content": "Hello, Plugin System!"
}
file_result = plugin_manager.execute_plugin("FileProcessor", file_data)
print(f"文件操作结果: {file_result}")
# 7. 演示插件热插拔
print("\n演示插件热插拔:")
print("卸载数据转换插件...")
plugin_manager.unload_plugin("DataTransformer")
print("当前插件列表:")
for plugin_name in plugin_manager.list_plugins():
print(f" - {plugin_name}")
# 8. 演示面向抽象编程
print("\n面向抽象编程演示:")
plugin_names = plugin_manager.list_plugins()
# 通过抽象接口调用所有插件
for plugin_name in plugin_names:
plugin = plugin_manager.get_plugin(plugin_name)
# 调用抽象方法
print(f"\n调用插件: {plugin.name}")
print(f" 描述: {plugin.description}")
print(f" 版本: {plugin.version}")
# 获取配置模式
schema = plugin.get_config_schema()
print(f" 配置模式类型: {schema.get('type', 'unknown')}")
print("\n=== 示例完成 ===")
if __name__ == "__main__":
main()
三、 抽象与具体的最佳实践
1. 抽象设计原则
# SOLID原则在抽象设计中的应用
from abc import ABC, abstractmethod
from typing import List
# 1. 单一职责原则(SRP):每个抽象只有一个职责
class UserRepository(ABC):
"""用户数据访问抽象 - 只负责数据访问"""
@abstractmethod
def find_by_id(self, user_id: str): pass
@abstractmethod
def save(self, user): pass
class UserValidator(ABC):
"""用户验证抽象 - 只负责验证"""
@abstractmethod
def validate(self, user): pass
# 2. 开闭原则(OCP):对扩展开放,对修改关闭
class PaymentProcessor(ABC):
@abstractmethod
def process(self, amount: float): pass
class CreditCardProcessor(PaymentProcessor):
def process(self, amount: float):
return f"信用卡支付: {amount}"
class PayPalProcessor(PaymentProcessor):
def process(self, amount: float):
return f"PayPal支付: {amount}"
# 可以添加新的支付方式而不修改现有代码
class CryptoProcessor(PaymentProcessor):
def process(self, amount: float):
return f"加密货币支付: {amount}"
# 3. 里氏替换原则(LSP):子类可以替换父类
class Bird(ABC):
@abstractmethod
def fly(self): pass
class Sparrow(Bird):
def fly(self):
return "麻雀在飞"
class Penguin(Bird):
def fly(self):
raise NotImplementedError("企鹅不会飞")
# 违反LSP原则:不能替换Bird
# 更好的设计:分离会飞和不会飞的鸟
class Bird(ABC):
@abstractmethod
def move(self): pass
class FlyingBird(Bird):
@abstractmethod
def fly(self): pass
def move(self):
return self.fly()
class NonFlyingBird(Bird):
@abstractmethod
def walk(self): pass
def move(self):
return self.walk()
# 4. 接口隔离原则(ISP):多个专用接口优于一个通用接口
# 不好的设计:一个巨大的接口
class Worker(ABC):
@abstractmethod
def work(self): pass
@abstractmethod
def eat(self): pass
@abstractmethod
def sleep(self): pass
# 好的设计:分离的接口
class Workable(ABC):
@abstractmethod
def work(self): pass
class Eatable(ABC):
@abstractmethod
def eat(self): pass
class Sleepable(ABC):
@abstractmethod
def sleep(self): pass
# 5. 依赖倒置原则(DIP):依赖抽象,不依赖具体
class Database(ABC):
@abstractmethod
def query(self, sql: str): pass
class MySQLDatabase(Database):
def query(self, sql: str):
return f"MySQL查询: {sql}"
class UserService:
# 依赖抽象,不依赖具体
def __init__(self, database: Database):
self.database = database
def get_user(self, user_id: str):
return self.database.query(f"SELECT * FROM users WHERE id = {user_id}")
2. 具体实现技巧
# 具体实现的优化技巧
import time
from functools import lru_cache
# 1. 性能优化:缓存具体实现的结果
class ExpensiveCalculation:
"""耗时的计算类"""
@lru_cache(maxsize=128)
def calculate(self, n: int) -> int:
print(f"计算 {n}...")
time.sleep(1) # 模拟耗时计算
return n * n
def calculate_without_cache(self, n: int) -> int:
print(f"计算 {n}...")
time.sleep(1)
return n * n
# 2. 内存优化:使用__slots__减少内存使用
class OptimizedUser:
"""使用__slots__优化内存的具体类"""
__slots__ = ['id', 'name', 'email'] # 固定属性列表
def __init__(self, id: str, name: str, email: str):
self.id = id
self.name = name
self.email = email
# 不能动态添加新属性,但内存使用更少
# 3. 延迟初始化:需要时才创建资源
class LazyResource:
"""延迟初始化的具体类"""
def __init__(self):
self._resource = None
@property
def resource(self):
if self._resource is None:
print("初始化资源...")
self._resource = self._create_resource()
return self._resource
def _create_resource(self):
# 创建资源的实际代码
return {"data": "expensive resource"}
# 4. 对象池模式:复用对象减少创建开销
class ConnectionPool:
"""数据库连接池的具体实现"""
def __init__(self, max_size: int = 10):
self.max_size = max_size
self.pool = []
self.in_use = set()
def get_connection(self):
# 尝试从池中获取可用连接
for conn in self.pool:
if conn not in self.in_use:
self.in_use.add(conn)
return conn
# 创建新连接
if len(self.pool) < self.max_size:
conn = self._create_connection()
self.pool.append(conn)
self.in_use.add(conn)
return conn
raise Exception("连接池已满")
def release_connection(self, conn):
self.in_use.remove(conn)
def _create_connection(self):
# 创建数据库连接的具体实现
return {"id": id(self), "status": "connected"}
四、 抽象与具体的优势对比
| 方面 | 抽象的优势 | 具体的优势 |
|---|---|---|
| 灵活性 | 易于扩展和修改 | 直接解决问题 |
| 复用性 | 通用接口,可跨项目复用 | 针对特定场景优化 |
| 测试性 | 易于模拟和测试 | 直接测试实际行为 |
| 维护性 | 修改实现不影响客户端 | 代码直观,易于理解 |
| 团队协作 | 接口明确,便于分工 | 实现具体,减少误解 |
| 复杂度 | 隐藏复杂性,简化使用 | 暴露细节,便于优化 |
五、 实际应用建议
-
合适的抽象层级:
- 不要过度抽象(避免"抽象泄露")
- 也不要过于具体(避免"硬编码")
- 根据变化频率设计抽象层级
-
抽象稳定性:
- 抽象接口一旦发布,应保持稳定
- 通过添加新方法扩展,而不是修改现有方法
- 使用版本控制管理抽象变更
-
具体实现的可替换性:
- 具体实现应该可以轻松替换
- 使用依赖注入管理具体实现
- 编写测试确保替换不影响功能
-
文档化:
- 抽象:说明接口契约、前置条件、后置条件
- 具体:说明实现细节、性能特征、限制条件
-
渐进式抽象:
从具体开始 → 发现重复模式 → 提取抽象 → 重构具体实现
抽象与具体是软件开发中最基本也最重要的思维工具。好的抽象让我们能够管理复杂性,好的具体实现让我们能够交付价值。掌握在两者之间自如切换的能力,能够在保持系统灵活性的同时,确保功能的正确性和性能。记住:面向抽象编程,面向具体实现,这是构建健壮、可维护软件系统的关键。
1354

被折叠的 条评论
为什么被折叠?



