23种设计模式----组合模式----结构型模式

组合模式

  • 1.什么是组合模式
  • 2.组合模式的角色
  • 3.核心思想
  • 4.例子—-目录遍历
    • 4.1抽象组合–目录
    • 4.2 实现组合–文件夹
    • 4.3 实现组合-文件
    • 4.4 目录类型
    • 4.5 组合异常
    • 4.6 测试方法–main方法
    • 4.7 结果
  • 5.总结

23种设计模式

1.什么是组合模式

日常生活中存在这样的一类型事物:
给你一个目录,你不知道是文件还是文件夹
给你一个链接,你不知道是具体的文本还是网页
一个大箱子可以容纳一个小箱子,这个小箱子又可以容纳更小的箱子。
同时,对一个分数进行二分,二分之一,四分之一,八分之一。。。
这就是递归,递归的本质就是递归的对象和本对象结构上完全相同。
还有比较著名的分形几何,都是递归实现的。

所以,为了解决递归,描述递归的对象,就有了组合模式。

2.组合模式的角色

抽象组合,
实现组合。
关系:

继承
继承
关联 实现组合1 抽象组合 实现组合2

3.核心思想

递归。

4.例子—-目录遍历

首先这是项目结构:
《23种设计模式----组合模式----结构型模式》

4.1抽象组合–目录

目录有可能是文件,也有可能是文件夹

import java.io.File;

import cn.com.startimes.composite.enums.CatalogType;
import cn.com.startimes.composite.exception.CompositeException;

/**
 * 目录
 * 文件夹和文件的抽象类
 * 一个目录类拥有这几种方法:
 * 1.判断一个目录是文件还是文件夹
 * 2.获取目录的 名字,类型,大小(类型,大小为file)
 * 3.增加目录到目录(folder)
 * 4.输出
 */
public abstract class Catalog {
	private String name;
	
	public abstract void scan(String path);
	
	public abstract String getSize() throws CompositeException;
	
	public abstract CatalogType getType();
	
	public abstract void add(Catalog catalog) throws CompositeException;

	public abstract void print(Catalog catalog);
	
	public Catalog(String name){
		this.name = name;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
}

4.2 实现组合–文件夹

import java.io.File;
import java.util.ArrayList;

import cn.com.startimes.composite.abs.Catalog;
import cn.com.startimes.composite.enums.CatalogType;
import cn.com.startimes.composite.exception.CompositeException;

/**
 * 文件夹类
 * 因为jdk中有File类等等,为了少一些
 * 麻烦,我们的叫做My+...
 */
public class MyFolder extends Catalog{

	private ArrayList<Catalog> catalogList = new ArrayList<Catalog>();
	
	private File file = null;
	
	public MyFolder(String name) {
		super(name);
	}
	
	@Override
	public void scan(String path) {
		file = new File(path);
		if(file.isDirectory()){
			for(File f:file.listFiles()){
				this.scan(f.getPath());
			}
		} else {
			Catalog catalog = new MyFile(file.getName());
			catalog.scan(file.getPath());
			this.add(catalog);
		}
	}

	@Override
	public String getSize() throws CompositeException {
		throw CompositeException.error(CompositeException.CAN_NOT_GET_FOLDER_SIZE);
	}

	@Override
	public CatalogType getType(){
		return CatalogType.FOLDER;
	}

	@Override
	public void add(Catalog catalog) {
		catalogList.add(catalog);
	}

	@Override
	public void print(Catalog catalog) {
		System.out.println(file.getPath());
		for(Catalog c:catalogList){
			c.print(c);
		}
	}
	
}

4.3 实现组合-文件

import java.io.File;

import cn.com.startimes.composite.abs.Catalog;
import cn.com.startimes.composite.enums.CatalogType;
import cn.com.startimes.composite.exception.CompositeException;

/**
 * 文件类,因为jdk中File类
 * 所以,我们的类叫做My+...
 *
 */
public class MyFile extends Catalog{

	private File file = null;
	
	public MyFile(String name) {
		super(name);
	}
	
	@Override
	public void scan(String path) {
		file = new File(path);
	}

	@Override
	public String getSize() throws CompositeException {
		return ((file.length()*100)/1024)/(double)100+"  k";
	}

	@Override
	public CatalogType getType() {
		return CatalogType.FILE;
	}

	@Override
	public void add(Catalog catalog) throws CompositeException{
		throw CompositeException.error(CompositeException.CAN_NOT_ADD_FOR_FILE);
	}

	@Override
	public void print(Catalog catalog) {
		try {
			System.out.println(file.getPath()+"    "+catalog.getSize());
		} catch (CompositeException e) {
			e.printStackTrace();
		}
	}
	
}

4.4 目录类型

public enum CatalogType {

	//文件
	FILE(1),
	//文件夹
	FOLDER(2);
	
	private Integer code;
	
	public static CatalogType valueOf(int ordinal){
		for(CatalogType catalogType:CatalogType.values()){
			if(ordinal == catalogType.code){
				return catalogType;
			}
		}
		return null;
	}
	
	private CatalogType(Integer code){
		this.code = code;
	}
	
	public void setCode(Integer code){
		this.code = code;
	}
	
	public Integer getCode(){
		return code;
	}
	
}

4.5 组合异常

public class CompositeException extends Exception{

	/**
	 * 
	 */
	private static final long serialVersionUID = 2521498032586564566L;

	public static final String CAN_NOT_GET_FOLDER_TYPE = "不能获取文件夹的类型";
	
	public static final String CAN_NOT_GET_FOLDER_SIZE = "不能获取文件夹的大小";
	
	public static final String CAN_NOT_ADD_FOR_FILE = "文件不能添加";
	
	public static CompositeException error(String message){
		System.out.println("---------error----------"+message);
		return new CompositeException();
	}
	
}

4.6 测试方法–main方法

import java.io.File;
import java.util.Scanner;

import cn.com.startimes.composite.abs.Catalog;
import cn.com.startimes.composite.impl.MyFile;
import cn.com.startimes.composite.impl.MyFolder;

public class Main {

	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("please input the root file/folder path");
		
		String path = scanner.next();
		
		File file = new File(path);
		
		Catalog catalog = null;
		if(file.isDirectory()){
			catalog = new MyFolder(path);
		} else {
			catalog = new MyFile(path);
		}
		
		catalog.scan(path);
		catalog.print(catalog);
		
		scanner.close();
		
	}

}

4.7 结果

文件夹

please input the root file/folder path
E:\Notepad++
E:\Notepad++\updater\README.md
E:\Notepad++\change.log    1.69  k
E:\Notepad++\contextMenu.xml    3.51  k
E:\Notepad++\functionList.xml    64.74  k
E:\Notepad++\langs.model.xml    320.44  k
E:\Notepad++\LICENSE    15.81  k
E:\Notepad++\localization\chineseSimplified.xml    69.06  k
E:\Notepad++\localization\english.xml    70.1  k
E:\Notepad++\notepad++.exe    3150.67  k
E:\Notepad++\NppShell_06.dll    224.67  k
E:\Notepad++\plugins\APIs\actionscript.xml    20.26  k
E:\Notepad++\plugins\APIs\BaanC.xml    18.05  k
E:\Notepad++\plugins\APIs\batch.xml    3.69  k
E:\Notepad++\plugins\APIs\c.xml    43.34  k
E:\Notepad++\plugins\APIs\cmake.xml    7.14  k
E:\Notepad++\plugins\APIs\coffee.xml    1.47  k
E:\Notepad++\plugins\APIs\cpp.xml    60.04  k
E:\Notepad++\plugins\APIs\cs.xml    15.01  k
E:\Notepad++\plugins\APIs\css.xml    11.25  k
E:\Notepad++\plugins\APIs\html.xml    19.1  k
E:\Notepad++\plugins\APIs\java.xml    200.55  k
E:\Notepad++\plugins\APIs\javascript.xml    21.39  k
E:\Notepad++\plugins\APIs\lisp.xml    15.82  k
E:\Notepad++\plugins\APIs\nsis.xml    7.99  k
E:\Notepad++\plugins\APIs\perl.xml    13.93  k
E:\Notepad++\plugins\APIs\php.xml    417.89  k
E:\Notepad++\plugins\APIs\python.xml    60.14  k
E:\Notepad++\plugins\APIs\rc.xml    1.6  k
E:\Notepad++\plugins\APIs\sql.xml    66.35  k
E:\Notepad++\plugins\APIs\tex.xml    66.28  k
E:\Notepad++\plugins\APIs\vb.xml    16.79  k
E:\Notepad++\plugins\APIs\vhdl.xml    2.57  k
E:\Notepad++\plugins\APIs\xml.xml    11.74  k
E:\Notepad++\plugins\Config\Hunspell\en_US.aff    2.97  k
E:\Notepad++\plugins\Config\Hunspell\en_US.dic    679.81  k
E:\Notepad++\plugins\DSpellCheck.dll    3159.17  k
E:\Notepad++\plugins\mimeTools.dll    117.17  k
E:\Notepad++\plugins\NppConverter.dll    153.67  k
E:\Notepad++\readme.txt    1.41  k
E:\Notepad++\SciLexer.dll    1400.17  k
E:\Notepad++\shortcuts.xml    1.54  k
E:\Notepad++\stylers.model.xml    161.94  k
E:\Notepad++\uninstall.exe    256.28  k
E:\Notepad++\updater\GUP.exe    204.67  k
E:\Notepad++\updater\gup.xml    3.87  k
E:\Notepad++\updater\libcurl.dll    533.17  k
E:\Notepad++\updater\LICENSE    7.62  k
E:\Notepad++\updater\README.md    2.92  k

文件

please input the root file/folder path
E:\Notepad++\change.log 
E:\Notepad++\change.log    1.69  k

5.总结

1.使用了模板方法的思想:
抽象类中规定子类必须实现的方法
2.异常对类的方法进行过滤:
比如作为文件夹类,不能使用获取大小的方法,但是又不能不实现,所以只好抛出异常或者使用空方法。
异常的使用还有一点,就是作为抽象类,定义的方法不是抽象方法,而是实际的方法,但是实际的方法中只有抛出异常的代码。这样写,如果子类覆盖了父类的方法,程序可以正常的运行,如果没有实现方法,那么就会抛出异常。
同时异常也是对方法的使用做的一个安全措施,某些类不能使用某些方法,如果使用了,就抛出异常。避免方法被使用,(类似野指针的野方法,你不知道在哪里被用到,特别是使用了模板方法或者适配器模式之后,方法的调用从显示到了隐式方面,所以这个是一个较好的方法)。
3.递归:
一般来说递归是自己调用自己,但是使用组合模式就是利用,在递归内部调用抽象类的递归方法,根据实例对象的不同,调用抽象递归不同的实现。
4.优点:
使用组合模式可以轻易的处理一大堆类似但是不完全相同的处理。使用封装继承等,可以完成大量相似但是不同的操作。
5.难点:
递归调用的方法,传入参数的不同,会调用不同的方法,这里是难点。
也是递归能否正确执行的关键。
23种设计模式

    原文作者:算法小白
    原文地址: https://blog.csdn.net/a18792721831/article/details/84143463
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞