结构型模式之:
- 适配器模式
- 桥接模式
- 代理模式
- 装饰模式
组合模式- 外观模式
- 享元模式
1.什么是组合模式
组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次关系。组合模式使得客户端可以统一处理单个对象和对象集合,而无需区分它们之间的差异。
这个组合模式,更像是什么呢?更像是递归树,忽略每个分支的下一个细节,通过泛型的方式去递归处理下一个分支。
举一个组合模式的例子:假设我们要创建一个文件系统的抽象表示,其中包含文件和文件夹两种类型的节点。文件夹可以包含文件和其他文件夹,文件是叶子节点,不包含其他节点。
首先,我们定义一个抽象基类 FileSystemComponent,它包含了文件和文件夹的公共操作:
// 抽象基类
public abstract class FileSystemComponent {
protected String name;
public FileSystemComponent(String name) {
this.name = name;
}
public abstract void print();
}
然后,我们定义文件类 File 和文件夹类 Folder,它们都是 FileSystemComponent 的子类:
// 文件类
public class File extends FileSystemComponent {
public File(String name) {
super(name);
}
@Override
public void print() {
System.out.println("File: " + name);
}
}
// 文件夹类
import java.util.ArrayList;
import java.util.List;
public class Folder extends FileSystemComponent {
private List<FileSystemComponent> children;
public Folder(String name) {
super(name);
children = new ArrayList<>();
}
public void add(FileSystemComponent component) {
children.add(component);
}
public void remove(FileSystemComponent component) {
children.remove(component);
}
//组合部分
@Override
public void print() {
System.out.println("Folder: " + name);
for (FileSystemComponent component : children) {
component.print();
}
}
}
在这个例子中,Folder 类可以包含其他的 File 和 Folder 对象,形成了一个树形结构。print() 方法通过递归调用,可以打印出整个文件系统的层次结构。
使用组合模式,我们可以轻松地操作文件和文件夹,统一了对它们的处理方式,使得客户端代码更加简洁和灵活。
2.组合模式的使用
前一段时间项目需求,针对服务端传送过来的json数据进行处理,但是json是负责的,类似于树结构一样,没有办法判定是不是到了最小拆分节点。也同样是使用到了组合模式。
举一个简单的例子,假设我们有一个 JSON 数据表示一个用户信息,其中包含了用户的基本信息和订单信息。该 JSON 数据可能如下所示:
{
"name": "John",
"age": 30,
"email": "john@example.com",
"orders": [
{
"id": "123456",
"product": "Laptop",
"price": 999.99
},
{
"id": "789012",
"product": "Smartphone",
"price": 699.99
}
]
}
怎么解析处理一个复杂的json呢?,一个复杂的json可能包含,jsonObject,jsonArray,JSONPrimitive(最小节点)
// 抽象基类 abstract class JSONComponent { public abstract void print(); }
// JSON 对象类
class JSONObject extends JSONComponent {
private List<JSONComponent> components = new ArrayList<>();
public void addComponent(JSONComponent component) {
components.add(component);
}
@Override
public void print() {
System.out.println("{");
for (JSONComponent component : components) {
component.print();
}
System.out.println("}");
}
}
// JSON 数组类
class JSONArray extends JSONComponent {
private List<JSONComponent> elements = new ArrayList<>();
public void addElement(JSONComponent element) {
elements.add(element);
}
@Override
public void print() {
System.out.println("[");
for (JSONComponent element : elements) {
element.print();
}
System.out.println("]");
}
}
// JSON 基本数据类型类
class JSONPrimitive extends JSONComponent {
private String value;
public JSONPrimitive(String value) {
this.value = value;
}
@Override
public void print() {
System.out.println("\"" + value + "\"");
}
}
public class Main {
public static void main(String[] args) {
// 构建 JSON 数据
JSONObject json = new JSONObject();
json.addComponent(new JSONPrimitive("name: John"));
json.addComponent(new JSONPrimitive("age: 30"));
json.addComponent(new JSONPrimitive("email: john@example.com"));
JSONArray orders = new JSONArray();
orders.addElement(new JSONObject().addComponent(new JSONPrimitive("id: 123456")).addComponent(new JSONPrimitive("product: Laptop")).addComponent(new JSONPrimitive("price: 999.99")));
orders.addElement(new JSONObject().addComponent(new JSONPrimitive("id: 789012")).addComponent(new JSONPrimitive("product: Smartphone")).addComponent(new JSONPrimitive("price: 699.99")));
json.addComponent(orders);
// 打印 JSON 数据
json.print();
}
}
在这个示例中,我们定义了抽象基类 JSONComponent,以及具体的子类 JSONObject、JSONArray 和 JSONPrimitive,分别用于表示 JSON 对象、JSON 数组和基本数据类型。然后我们构建了一个包含用户信息和订单信息的 JSON 数据,并通过组合模式来表示和打印这个 JSON 数据。
3.组合模式的使用场景
- 树形结构的数据表示: 当数据具有层次结构,且每个节点都可以包含子节点时,可以使用组合模式。例如,文件系统中的文件和文件夹,以及菜单系统中的菜单和菜单项等都可以使用组合模式来表示。
- 统一处理叶子和组合对象: 组合模式允许客户端统一处理叶子对象和组合对象,因为它们都实现了相同的接口。这样客户端可以一致性地处理整个对象结构。
- 简化客户端代码: 客户端无需关心对象是叶子还是组合,只需通过统一的接口来操作对象。这简化了客户端的代码,使其更加清晰和易于维护。
- 动态组合对象: 组合模式允许动态地向组合对象中添加或移除子对象,而无需修改客户端代码。这使得对象的组织结构可以灵活地调整和扩展。
4.组合模式的优缺点
优点:
- 你可以利用多态和递归机制更方便地使用复杂树结构。
- 开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
缺点:
- 设计复杂性增加: 实现组合模式需要定义抽象组件、叶子组件和组合组件等多个类,并且需要合理地设计它们之间的关系,因此会增加系统的设计复杂性。
- 不易限制组件类型: 组合模式将叶子对象和组合对象统一对待,因此可能导致在组合对象中添加了不合适的子对象,或者在叶子对象中执行了不适当的操作。
- 不适合过于简单或过于复杂的情况: 对于过于简单的对象结构或过于复杂的对象结构,组合模式可能会显得不够灵活或不够直观,不适合使用。
- 性能问题: 组合模式可能会在遍历整个对象结构时产生额外的开销,特别是在深层次的嵌套结构中,遍历和操作可能会导致性能下降