0
点赞
收藏
分享

微信扫一扫

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.难点:
递归调用的方法,传入参数的不同,会调用不同的方法,这里是难点。
也是递归能否正确执行的关键。​


举报

相关推荐

0 条评论