一,什么是组合模式
Composite 模式 也叫组合模式,是构造型的设计模式之一,通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树
二,组合模式的结构
组合模式的角色和职责
Component : (树形结构的节点抽象)
- 为所有的对象定义统一的接口,(公共属性,行为等的定义)
- 提供管理子节点对象的接口方法
- (选择)提供管理父节点对象的接口方法
Leaf : (树形结构的叶节点)
Composite: (树形结构的枝节点)
优点:
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点:
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
- 不容易用继承的方法来增加构件的新功能;
组合模式分为透明式的组合模式和安全式的组合模式。
四:透明方式代码实现:
透明方式:在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。

Component
public interface IFile {
/**
* @Description: 显示文件夹的名称
* @param:
* @return: void
**/
public void display();
/**
* @Description: 添加
* @param: []
* @return: boolean
**/
public boolean add(IFile iFile);
/**
* @Description: 删除
* @param: []
* @return: boolean
**/
public boolean remove(IFile iFile);
/**
* @Description: 获得子节点
* @param: []
* @return: java.util.List<com.enjoy.cap26.IFile>
**/
public List<IFile> getChildren();
}
Leaf
/**
* @ClassName Files
* @Description TODO
* @Version 1.0
**/
public class Files implements IFile{
private String name;
public Files(String name) {
this.name = name;
}
@Override
public void display() {
System.out.println(name);
}
@Override
public boolean add(IFile iFile) {
return false;
}
@Override
public boolean remove(IFile iFile) {
return false;
}
@Override
public List<IFile> getChildren() {
return null;
}
}
Composite
/**
* @ClassName Folder
* @Description TODO
* @Version 1.0
**/
public class Folder implements IFile{
private String name;
private List<IFile> children;
public Folder(String name) {
this.name = name;
children = new ArrayList<IFile>();
}
@Override
public void display() {
System.out.println(name);
}
@Override
public boolean add(IFile iFile) {
return children.add(iFile);
}
@Override
public boolean remove(IFile iFile) {
return children.remove(iFile);
}
@Override
public List<IFile> getChildren() {
return children;
}
}
测试:
/**
* @ClassName test
* @Description TODO
* @Version 1.0
**/
public class Test {
public static void main(String[] args) {
//父节点
Folder folder = new Folder("D:");
//子节点 目录
Folder javaFoder = new Folder("java");
//子节点 helloworld.txt
Files files = new Files("helloworld.txt");
folder.add(javaFoder);
folder.add(files);
Folder sprFoder = new Folder("spring");
Files files2 = new Files("springAop-api");
javaFoder.add(sprFoder);
javaFoder.add(files2);
//子节点 目录
Folder stuFoder = new Folder("学习");
Files files1 = new Files("String.txt");
folder.add(stuFoder);
folder.add(files1);
displayTree(folder,0);
}
/**
* 使用递归
* @param iFile
* @param deep
*/
public static void displayTree(IFile iFile,int deep){
for (int i = 0; i < deep;i++){
System.out.print("--");
}
//显示自身名称
iFile.display();
List<IFile> children = iFile.getChildren();
for (IFile file : children) {
if( file instanceof Files){
for (int i = 0; i <= deep;i++){
System.out.print("---");
}
file.display();
}else{
displayTree(file,deep+1);
}
}
}
}

五,安全方式
安全方式:在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。

Component
/**
* @ClassName Articles
* @Description 抽象构建
* @Version 1.0
**/
public interface Articles {
/**
* @Description: 计算
* @param: []
* @return: float
* @Author: wuchao
* @Date: 2020/6/26 20:31
**/
public float calculation();
/**
* @Description: 显示
* @param: []
* @return: void
* @Author: wuchao
* @Date: 2020/6/26 20:32
**/
public void show();
}
leaf:
/**
* @ClassName Goods
* @Description 树叶构件
* @Version 1.0
**/
public class Goods implements Articles{
private String name;
/**
* 数量
*/
private int quantity;
/**
* 单价
*/
private float unitPrice;
public Goods(String name, int quantity, float unitPrice) {
this.name = name;
this.quantity = quantity;
this.unitPrice = unitPrice;
}
@Override
public float calculation() {
return quantity*unitPrice;
}
@Override
public void show() {
System.out.println(name+"(数量:"+quantity+",单价:"+unitPrice+"元)");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public float getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(float unitPrice) {
this.unitPrice = unitPrice;
}
}
Composite
/**
* @ClassName Bags
* @Description TODO
* @Version 1.0
**/
public class Bags implements Articles{
private String name;
private List<Articles> list;
public Bags(String name) {
this.name = name;
list = new ArrayList<Articles>();
}
@Override
public float calculation() {
float s=0;
for(Object obj:list)
{
s+=((Articles)obj).calculation();
}
return s;
}
@Override
public void show() {
for(Object obj:list) {
((Articles)obj).show();
}
}
/**
* 新增对象
* @param c
*/
public void add(Articles c) {
list.add(c);
}
/**
* 删除对象
* @param c
*/
public void remove(Articles c) {
list.remove(c);
}
/**
* 获得list
* @return
*/
public List<Articles> getChild(){
return list;
}
}
测试:
public class Test {
public static void main(String[] args) {
float s=0;
Bags BigBag,mediumBag,smallRedBag,smallWhiteBag;
Goods sp;
BigBag=new Bags("大袋子");
mediumBag=new Bags("中袋子");
smallRedBag=new Bags("红色小袋子");
smallWhiteBag=new Bags("白色小袋子");
sp=new Goods("婺源特产",2,7.9f);
smallRedBag.add(sp);
sp=new Goods("婺源地图",1,9.9f);
smallRedBag.add(sp);
sp=new Goods("韶关香菇",2,68);
smallWhiteBag.add(sp);
sp=new Goods("韶关红茶",3,180);
smallWhiteBag.add(sp);
sp=new Goods("景德镇瓷器",1,380);
mediumBag.add(sp);
mediumBag.add(smallRedBag);
sp=new Goods("李宁牌运动鞋",1,198);
BigBag.add(sp);
BigBag.add(smallWhiteBag);
BigBag.add(mediumBag);
System.out.println("您选购的商品有:");
BigBag.show();
s=BigBag.calculation();
System.out.println("要支付的总价是:"+s+"元");
}
}
六,组合模式的应用场景
- 在需要表示一个对象整体与部分的层次结构的场合。
- 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
本文深入探讨了组合模式,一种构造型设计模式,用于构造树形对象结构,使客户端能够一致地处理单个对象和组合对象。文章详细解析了组合模式的结构、角色职责、优缺点,以及透明式和安全式两种实现方式,并提供了具体代码实例。

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



