Java设计模式学习总结:组合模式
一、概述
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构:
在面向对象设计时,我们经常遇到一类具有容器特征的对象,它们充当着普通对象的同时,还充当着其它对象的容器,这些对象称为容器对象,而那些只能充当普通对象的对象则称为叶子对象。在容器中既可以包含叶子对象,也可以包含容器对象。例如,在树形目录结构中,包含文件和文件夹两类不同的元素:
1、在文件夹中可以包含文件,还可以继续包含子文件夹
2、在文件中不能再包含子文件或者子文件夹
那么文件夹对象为容器(Container)对象,则文件对象为叶子(Leaf)对象。
当容器对象的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理。
由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下客户端希望一致地处理它们,因为对于这些对象的区别对待将会使程序非常复杂。
二、组合模式的定义
如何一致地对待容器对象和叶子对象?我们学个新的模式:组合模式。
组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,它描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待容器对象和叶子对象。
组合模式:组合多个对象形成树形结构以表示具有部分和整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。Composite Pattern: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Component(抽象构件)
Leaf(叶子构件)
Composite(容器构件)
public abstract class Component {
public abstract void add(Component c); //增加成员
public abstract void remove(Component c); //删除成员
public abstract Component getChild(int i); //获取成员
public abstract void operation(); //业务方法
}
public class Leaf extends Component {
public void add(Component c) {
//异常处理或错误提示
}
public void remove(Component c) {
//异常处理或错误提示
}
public Component getChild(int i) {
//异常处理或错误提示
return null;
}
public void operation() {
//叶子构件具体业务方法的实现
}
}
public class Composite extends Component {
private ArrayList<Component> list = new ArrayList<Component>();
public void add(Component c) {
list.add(c);
}
public void remove(Component c) {
list.remove(c);
}
public Component getChild(int i) {
return (Component)list.get(i);
}
public void operation() {
//容器构件具体业务方法的实现,将递归调用成员构件的业务方法
for(Object obj:list) {
((Component)obj).operation();
}
}
}
三、案例
某软件公司欲开发一个杀毒(Antivirus)软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现使用组合模式来设计该杀毒软件的整体框架。
package com.test;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
//针对抽象构件编程
AbstractFile file1,file2, folder ;
folder = new Folder(\”图像文件\”);
file1 = new ImageFile(\”上官婉儿.jpg\”);
file2 = new ImageFile(\”王昭君.gif\”);
folder .add(file1);
folder .add(file2);
folder.killVirus();
}
}
abstract class AbstractFile {
public abstract void add(AbstractFile file);
public abstract void remove(AbstractFile file);
public abstract AbstractFile getChild(int i);
public abstract void killVirus();
}
class Folder extends AbstractFile {
//定义集合fileList,用于存储AbstractFile类型的成员
private ArrayList<AbstractFile> fileList=new ArrayList<AbstractFile>();
private String name;
public Folder(String name) {
this.name = name;
}
public void add(AbstractFile file) {
fileList.add(file);
}
public void remove(AbstractFile file) {
fileList.remove(file);
}
public AbstractFile getChild(int i) {
return (AbstractFile)fileList.get(i);
}
public void killVirus() {
System.out.println(\”****对文件夹\’\” + name + \”\’进行杀毒\”); //模拟杀毒
//递归调用成员构件的killVirus()方法
for(Object obj : fileList) {
((AbstractFile)obj).killVirus();
}
}
}
class ImageFile extends AbstractFile {
private String name;
public ImageFile(String name) {
this.name = name;
}
public void add(AbstractFile file) {
System.out.println(\”对不起,不支持该方法!\”);
}
public void remove(AbstractFile file) {
System.out.println(\”对不起,不支持该方法!\”);
}
public AbstractFile getChild(int i) {
System.out.println(\”对不起,不支持该方法!\”);
return null;
}
public void killVirus() {
//模拟杀毒
System.out.println(\”—-对图像文件\’\” + name + \”\’进行杀毒\”);
}
}
//TextFile和VideoFile和上述类似,略
运行结果:
本资料案例主要学习 《Java设计模式 中南大学 刘伟》之后总结,其中程序读者亲自在myEclipse8.5版本调试通过,注意本人所有的类和接口写在一个Java文件里面,除了主类其它类和接口不能声明为public的,主要是提醒出道时间不长的读者,以免造成学习上的麻烦,但重在多试,有问题是好事。
组合模式使用的场景:
1、在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们
2、在一个使用面向对象语言开发的系统中需要处理一个树形结构
3、在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型
Java程序员必须掌握的15个设计模式,特点和使用场景汇总整理!
设计模式是一种广泛使用的编程思想,它是一种用于解决特定问题的经验性方法,提供了一套通用的解决方案,可用于不同的应用场景,可以帮助我们解决常见的问题并提高代码的可重用性和可维护性。
设计模式分为三类:创建型设计模式、结构型设计模式和行为型设计模式。
创建型设计模式用于封装对象的创建过程,它们可以帮助我们在不暴露对象创建过程的情况下创建对象。以下是常见的创建型设计模式:
工厂方法模式(Factory Method Pattern)是一种用于封装对象创建过程的模式。它定义了一个创建对象的接口,但让子类决定实例化哪个类。工厂方法使得一个类的实例化延迟到其子类。
优点:子类可以在运行时决定创建的对象类型,而且可以避免客户端与具体类耦合。同时,它也很容易增加新的产品线。
使用场景:当我们需要隐藏对象创建过程,并让客户端通过抽象接口来创建对象时,可以考虑使用工厂方法模式。例如,当我们需要创建不同的消息对象时,可以使用工厂方法模式来创建消息对象。
抽象工厂模式(Abstract Factory Pattern)是一种用于创建相关或独立对象族的模式。它提供了一种接口,该接口可以创建一系列产品,但不需要指定具体的产品类。
优点:它可以隐藏产品的具体实现,以及如何创建这些产品。同时,它也使得客户端可以独立于具体的产品创建过程。
使用场景:当我们需要创建一系列相关或独立的对象时,可以考虑使用抽象工厂模式。例如,当我们需要创建一系列不同类型的手机和电视时,可以使用抽象工厂模式。
单例模式(Singleton Pattern)是一种用于限制类的实例化次数的模式。它保证一个类只有一个实例,并提供全局访问点。
优点:它可以节省系统资源,并且可以避免多个对象之间的冲突。
使用场景:当一个类只需要一个实例时,可以考虑使用单例模式。例如,当一个类需要负责管理应用程序的配置信息时,可以使用单例模式。
建造者模式(Builder Pattern)是一种用于封装复杂对象构建过程的模式。它将对象的构建和表示分离,使得相同的构建过程可以创建不同的表示。
优点:它可以灵活地创建对象,并且可以避免重复的构建过程。同时,它也很容易扩展,因为每个部件都是独立的。
使用场景:当我们需要构建一些复杂的对象时,可以考虑使用建造者模式,例如,当我们需要创建一个电子商品时,可以使用建造者模式来创建商品对象。
原型模式(Prototype Pattern)是一种用于创建对象的模式,它通过复制现有的对象来创建新的对象。原型模式通过克隆现有对象来创建新对象,而不是通过调用构造函数。
优点:它可以减少对象创建的开销,并且可以最大限度地利用已有对象。同时,它还可以避免构造函数的限制。
使用场景:当我们需要创建大量相似的对象时,可以考虑使用原型模式,例如,当我们需要创建多个相似的线图或柱图对象时,可以使用原型模式来复制现有的对象。
结构型设计模式用于将对象组合成更大、更复杂的结构,以便于更好地组织代码。以下是常见的结构型设计模式:
适配器模式(Adapter Pattern)是一种用于将不兼容的对象转换为兼容对象的模式。它通过使一个类的接口适用另一个接口来完成这个过程。适配器模式既可以是类适配器,也可以是对象适配器。
优点:它可以使得原本不兼容的对象可以协同工作。同时,它还可以减少代码的冗余。
使用场景:当我们需要将一个类的接口转换为其他类所期望的接口时,可以考虑使用适配器模式。例如,当我们需要将一个第三方类库的接口转换为我们的应用程序所期望的接口时,可以使用适配器模式。
桥接模式(Bridge Pattern)是一种用于将抽象和实现分离的设计模式。它通过使用一个中间类来链接抽象和实现,使得它们可以独立地变化。
优点:它可以减少类之间的耦合,并且可以使得抽象和实现可以独立地进行变化。
使用场景:当我们需要将抽象和实现分离,并且需要对它们进行独立的变化时,可以考虑使用桥接模式。例如,当我们需要将一个笔刷分为硬笔刷和软笔刷时,可以使用桥接模式来实现。
组合模式(Composite Pattern)是一种用于将对象组成树形结构的模式。它将单个对象和组合对象中的对象统一看作一个对象,这样用户无需了解其中细节即可处理它们。
优点:它可以简化客户端代码,并且可以使得增加或删除节点时非常容易。
使用场景:当我们需要组合单个对象和组合对象时,可以使用组合模式。例如,当我们需要创建一个菜单时,可以使用组合模式来组合不同的菜单项。
装饰器模式(Decorator Pattern)是一种用于动态地给对象添加职责的模式。它在不改变原有类的基础上,通过将对象包装在一个装饰器类中,来实现对对象功能的扩展。
优点:它可以在运行时动态地扩展一个对象的职责,而不需要修改源代码。同时,它也很容易扩展,因为每个装饰器都是独立的。
使用场景:当我们需要在运行时动态地扩展一个对象的功能时,可以考虑使用装饰器模式。例如,当我们需要给某个对象动态地添加日志、验证或缓存等功能时,可以使用装饰器模式。
外观模式(Facade Pattern)是一种用于隐藏复杂子系统的复杂性,并提供一个简单接口的模式。外观模式将复杂的子系统组合在一起,并提供一个简单接口来简化客户端调用。
优点:它可以简化客户端代码,并且可以隔离复杂子系统的实现细节。
使用场景:当我们需要对复杂子系统进行封装,并提供一个简单接口时,可以考虑使用外观模式。例如,当我们需要对数据库进行操作时,可以使用外观模式来封装数据库访问过程。
行为型设计模式关注对象之间的通信和协作。以下是常见的行为型设计模式:
策略模式(Strategy Pattern)是一种用于定义一系列算法,以及提供一种在运行时可以切换算法的方式的模式。该模式允许算法独立于客户端而变化。
优点:它可以很容易地替换算法,并且可以避免使用大量的条件语句。同时,它也可以提高代码的可扩展性和可维护性。
使用场景:当我们需要在运行时根据不同的需求选择不同的算法时,可以考虑使用策略模式。例如,当我们需要根据不同的用户类型计算不同的折扣时,可以使用策略模式来实现。
观察者模式(Observer Pattern)是一种用于对象之间的一对多依赖关系的模式。当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新状态。
优点:它可以使得对象之间的耦合度更低,并且可以提高代码的可维护性和可扩展性。
使用场景:当我们需要建立对象之间一对多的依赖关系时,可以考虑使用观察者模式。例如,当我们需要实现一个简单的消息通知系统时,可以使用观察者模式来实现。
命令模式(Command Pattern)是一种将请求封装成对象的模式,以便于存储、传递和使用。命令模式将请求接收者和请求发送者从彼此解耦,使得请求可以被重复执行、取消和排队。
优点:它可以对请求进行操作,并且可以灵活地添加新的命令,同时也可以很容易地撤销和重做操作。
使用场景:当我们需要对操作进行封装,并且需要支持撤销和重做操作时,可以考虑使用命令模式。例如,当我们需要实现一个简单的文本编辑器时,可以使用命令模式来实现。
迭代器模式(Iterator Pattern)是一种提供一种方法顺序访问聚合对象中各个元素的模式。迭代器模式将集合和遍历操作分离开来,使得可以对集合进行不同方式的遍历,而无需改变集合本身的结构。
优点:它可以隔离遍历算法和数据结构,并且可以简化遍历代码。
使用场景:当我们需要遍历一系列对象时,可以考虑使用迭代器模式。例如,当我们需要对一个图像集合进行遍历时,可以使用迭代器模式来实现。
责任链模式(Chain of Responsibility Pattern)是一种用于将多个处理对象连成一条链,并依次处理请求的模式。每个处理对象都可以决定是否处理请求,以及是否将请求传递给下一个处理对象。
优点:它可以避免客户端和处理对象之间的耦合,同时也可以提高代码的可扩展性和可维护性。
使用场景:当我们需要将请求发送给多个处理对象,并且让它们依次处理请求时,可以考虑使用责任链模式。例如,当我们需要处理一个订单时,可以使用责任链模式来处理订单状态的变化。
本文介绍了三种常见的设计模式:创建型设计模式、结构型设计模式和行为型设计模式。这些模式都有各自的优点和使用场景,可以帮助开发人员更好地组织代码,并提高代码的可扩展性和可维护性。在实际开发过程中,我们应该根据不同的需求选择不同的模式,并灵活地使用它们。
在后续的文章合集中,我会详细介绍每一种设计模式的原理及其使用场景,请关注我的后续文章。【】
对于本文中整理的设计模式,不知道你有没有什么看法,欢迎在评论区里留言。如果你对我的文章内容感兴趣,请点击关注,谢谢支持! [谢谢][谢谢][谢谢]
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。