《Java设计模式》之合成模式

合成模式

合成模式把部分和整体关系用树结构表示,是属于对象的结构模式。合成模式要对组合的对象进行管理,所以在一定位置给予对象的相关管理方法,如:add(),remove()等.合成模式中对象的管理有两种方案。

1.安全方式:此方式只允许树枝构件有对象的管理方法。

2.透明方式:此方式只允许树枝和树叶都有对象的管理方法,但树叶对象中的管理方法无实际意义。

一.UML示意图

二.组成部分

抽象构件:抽象组合对象的公共行为接口

树叶构件:树叶对象,没有下级子对象

树枝构件:树枝对象,树枝对象可以包含一个或多个其他树枝或树叶对象

三.代码例子:我以一个超市购物为例

(一)、安全方式

1.抽象物品(抽象构件)

package com.eekq.structure.composite.security;
/*
 * 抽象构件,物品
 * */
public interface IRes {
    /**购物买单,示意性的商业方法*/
    public void pay();
}

2.单一物品(树叶构件)

package com.eekq.structure.composite.security;
public class SingleResImpl implements IRes {
    /**物品名称*/
    private String name;
    /**价钱*/
    private float money;
    public SingleResImpl(String name, float money) {
        this.name = name;
        this.money = money;
    }
    public void pay() {
        System.out.println("购买了一件物品["+getName()+"],价钱是[" + getMoney()+"]元");
    }
    public float getMoney() {
        // TODO 自动生成方法存根
        returnthis.money;
    }
    public String getName() {
        // TODO 自动生成方法存根
        return this.name;
    }
    /**重写equals*/
    public boolean equals(Object obj){
        SingleResImpl res = (SingleResImpl)obj;
        return res.getName().equals(getName()) && res.getMoney()==getMoney();
    }
}

3.多个物品(树枝构件)

package com.eekq.structure.composite.security;
import java.util.Iterator;
import java.util.Vector;
/*
 * 对多个物品的管理
 * */
public class MultiResImpl implements IRes {
    /**购物车*/
    private Vector car = new Vector();
    private static float totle = 0.0f;

public void pay() {
        if(!car.isEmpty()){
        System.out.println("名称        价格\n");
        shopping();
        System.out.println("\n总价:" + totle + "元");
        }else{
            System.out.println("您好,你没有购买任何物品,不用买单!");
        }
    }
    public void shopping() {
        if (car != null || !car.isEmpty()) {
            Iterator it = car.iterator();
            SingleResImpl res = null;
            Object temp = null;// 临时对象
            while (it.hasNext()) {
                temp = it.next();
                if (temp instanceof MultiResImpl) {
                    ((MultiResImpl) temp).shopping();
                } else {
                    res = (SingleResImpl) temp;
                    synchronized (this) {
                        totle += res.getMoney();
                    }
                    System.out.println(res.getName() + "            " + res.getMoney()
                            + "元");
                }
            }
        }
    }
    /**加入新的物品*/
    public void addRes(IRes res) {
        car.add(res);
    }

    /**放回物品*/
    public void removeRes(IRes res) {
        car.remove(res);
    }

}
 

4.收银台买单

package com.eekq.structure.composite.security;
public class Main {
    /**
     *@paramargs
     */
    public static void main(String[] args) {
        /**买支雪糕*/
        IRes singleRes = new SingleResImpl("雪糕", 1.5f);
        /**买单*/
        singleRes.pay();

        /**快过年了,我推了个购物车,多买点东西*/
        IRes allRes = new MultiResImpl();
        /**在一楼买的食物*/
        IRes one = new MultiResImpl();
        ((MultiResImpl) allRes).addRes(one);//把一楼的东西装在购物车里
        /**因为是安全方式的组合模式,因此不够透明,只能明确的向下转型,然后再加入购物车了*/
        ((MultiResImpl) one).addRes(new SingleResImpl("旺旺", 28.5f));
        ((MultiResImpl) one).addRes(new SingleResImpl("糖果", 38.0f));
        ((MultiResImpl) one).addRes(new SingleResImpl("可乐", 8.5f));

        /**二楼去买的衣服和袜子*/
        IRes two = new MultiResImpl();
        ((MultiResImpl) allRes).addRes(two);// 把二楼的东西装也装在购物车里
        ((MultiResImpl) two).addRes(new SingleResImpl("衣服", 130.5f));
        ((MultiResImpl) two).addRes(new SingleResImpl("袜子", 10f));
        /**二楼再买了个手表,我放在bao里*/
        IRes bao = new MultiResImpl();
        ((MultiResImpl) two).addRes(bao);//把购物小包装在二楼购物车里
        ((MultiResImpl) bao).addRes(new SingleResImpl("手表", 100f));

        /**回到一楼,又买了苹果和梨*/
        ((MultiResImpl) one).addRes(new SingleResImpl("苹果", 10.0f));
        ((MultiResImpl) one).addRes(new SingleResImpl("梨", 3.0f));
/**在买单之前我把可乐退了,因为家里还有的嘛*/
        ((MultiResImpl) one).removeRes(new SingleResImpl("可乐", 8.5f));
        /**在收银台一次性对购物车所有物品买单*/
        allRes.pay();
    }
}

5.运行结果

购买了一件物品[雪糕],价钱是[1.5]元

名称        价格

旺旺        28.5元

糖果        38.0元

苹果        10.0元

梨          3.0元

衣服        130.5元

袜子        10.0元

手表        100.0元

总价:320.0元

(二)、透明方式

透明方式与安全方式的不同点在于抽象构件,透明方式使用的是统一接口。

1. 抽象构件

package com.eekq.structure.composite.clarity;

/*
 * 抽象构件,物品
 * */
public interface IRes {
    /**购物买单,示意性的商业方法*/
    public void pay();

    /**加入新的物品*/
    public void addRes(IRes res);

    /**放回物品*/
    public void removeRes(IRes res);
}

2. 单一物品(树叶构件)

package com.eekq.structure.composite.security;

public class SingleResImpl implements IRes {

    /**物品名称*/
    private String name;

    /**价钱*/
    private float money;

    public SingleResImpl(String name, float money) {
        this.name = name;
        this.money = money;
    }

    public void pay() {
        System.out.println("购买了一件物品["+getName()+"],价钱是[" + getMoney()+"]元");
    }

    public float getMoney() {
        // TODO 自动生成方法存根
        return this.money;
    }

    public String getName() {
        // TODO 自动生成方法存根
        return this.name;
    }

    /**重写equals*/
    public boolean equals(Object obj){
        SingleResImpl res = (SingleResImpl)obj;
        return res.getName().equals(getName()) && res.getMoney()==getMoney();
    }

}

3.多个物品(树枝构件)

同安全模式代码一样!

4.收银台买单

package com.eekq.structure.composite.clarity;
public class Main {
    /**
     *@paramargs
     */
    public static void main(String[] args) {
        /**买支雪糕*/
        IRes singleRes = new SingleResImpl("雪糕", 1.5f);
        /**买单*/
        singleRes.pay();
        /**快过年了,我推了个购物车,多买点东西*/
        IRes allRes = new MultiResImpl();

        /**在一楼买的食物*/
        IRes one = new MultiResImpl();
        allRes.addRes(one);// 把一楼的东西装在购物车里
        /**因为是透明方式的组合模式,因此直接调用就是了*/
        one.addRes(new SingleResImpl("旺旺", 28.5f));
        one.addRes(new SingleResImpl("糖果", 38.0f));
        one.addRes(new SingleResImpl("可乐", 8.5f));

        /**二楼去买的衣服和袜子*/
        IRes two = new MultiResImpl();
        allRes.addRes(two);// 把二楼的东西装也装在购物车里
        two.addRes(new SingleResImpl("衣服", 130.5f));
        two.addRes(new SingleResImpl("袜子", 10f));
        /**二楼再买了个手表,我放在bao里*/
        IRes bao = new MultiResImpl();
        two.addRes(bao);// 把购物小包装在二楼购物车里
        bao.addRes(new SingleResImpl("手表", 100f));
        /**回到一楼,又买了苹果和梨*/
        one.addRes(new SingleResImpl("苹果", 10.0f));
        one.addRes(new SingleResImpl("梨", 3.0f));
        /**在买单之前我把可乐退了,因为家里还有的嘛*/
        one.removeRes(new SingleResImpl("可乐", 8.5f));
        /**在收银台一次性对购物车所有物品买单*/
        allRes.pay();
    }
}

5.运行结果

同安全模式一样的结果!

四.总结

合成模式是对象的结构模式,以上演示合成模式。在以后的项目中,如果遇到对象组合的情况,即也符合树结构的。可以考虑下此模式。此模式中讲述了安全方式和透明方式。

安全方式:抽象构件上只提供树叶和树枝公共的方法,没提供树枝独有的管理等方法(add(),remove())。这样的好处是安全,用户不会在树叶上使用add()等管理方法,缺点是不够透明,用户必须知识当前对象为树叶还是树枝(向下转型)。

透明方式:抽象构件上提供了满足树枝的所有方法(包括add(),remove()),这样做的好处是,用户可以任意执行对象的add()和remove()管理对象。缺点是如果用户在树叶上执行管理方式(add(),remove())时,在编译期不会有错,但在执行期会报错,这样不容易被发觉错误出在哪.

如果以上内容不明白,推荐博客地址:

http://lavasoft.blog.51cto.com/62575/90824/

下面的资料来源:

Steven John Metsker   和william C. wake 著 的  java设计模式(第二版)第五章内容:

仅供大家参考和学习!

版权声明:欢迎转载,希望在你转载的同时,添加原文地址,谢谢配合

时间: 2024-10-24 16:24:07

《Java设计模式》之合成模式的相关文章

JAVA设计模式之合成模式

在阎宏博士的<JAVA与模式>一书中开头是这样描述合成(Composite)模式的: 合成模式属于对象的结构模式,有时又叫做“部分——整体”模式.合成模式将对象组织到树结构中,可以用来描述整体与部分的关系.合成模式可以使客户端将单纯元素与复合元素同等看待. 合成模式 合成模式把部分和整体的关系用树结构表示出来.合成模式使得客户端把一个个单独的成分对象和由它们复合而成的合成对象同等看待. 比如,一个文件系统就是一个典型的合成模式系统.下图是常见的计算机XP文件系统的一部分. 从上图可以看出,文件

JAVA设计模式之代理模式

学编程吧JAVA设计模式之代理模式发布了,欢迎通过xuebiancheng8.com来访问 一.概述 给某一个对象提供一个代理,并由代理对象来完成对原对象的访问.代理模式是一种对象结构型模式. 二.适用场景 当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口. 三.UML类图 四.参与者 1.接口类:Subject 它声明了真实访问者和代理访问者的共同接口,客户端通常需要针对接口角色进行编程. 2.代理类

浅析JAVA设计模式之工厂模式(一)

1 工厂模式简介 工厂模式的定义:简单地说,用来实例化对象,代替new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式可以动态决定将哪一个类实例化,不用先知道每次要实例化哪一个类. 工厂模式可以分一下三种形态: 简单工厂 (Simple Factory)模式:又称静态工厂模式(StaticFactory). 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory). 抽象工厂 (Abstract Factroy)模式:又称工具箱模式

浅析JAVA设计模式之工厂模式(二)

1 工厂方法模式简介 工厂方法 (Factroy Method) 模式:又称多态性工厂模式(Polymorphic Factory),在这种模式中,核心工厂不再是一个具体的类,而是一个抽象工厂,提供具体工厂实现的接口,具体创建产品交由子工厂去做,抽象工厂不涉及任何产品被实例化的细节.而不同等级的产品,就对应一个不同等级的工厂,如下图. 图1 1.1工厂方法模式(多态性工厂模式): 工厂方法模式有三个角色: 1. 抽象产品接口 2. 具体产品类 3. 抽象工厂接口 4.具体工厂类. 1.2工厂方法

JAVA设计模式(3)----代理模式

1.  什么是代理模式?Proxy Pattern 代理模式定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 通俗的讲,代理模式就是我很忙没空理你,你要想找我可以先找我的代理人,代理人和被代理人继承同一个接口.代理人虽然不能干活,但是被代理的人可以干活. 这个例子中有水浒传中的这么几个人:名垂青史的潘金莲,王婆,西门大官人.西门庆想要找潘金莲,需要找王婆做代理.首先定义一个接口:Kin

java设计模式------装饰着模式

java设计模式-------装饰者模式 装饰者模式 Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案.主要有组件(components)和装饰器(Decorator)组成.要求components和Decorator实现相同的接口或者抽象类(具体类的局限性太大). 设计原则.模式特点.适用性 - 1. 多用组合,少用继承. 利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为.然而,如果能够利用

浅析JAVA设计模式之工厂模式(三)

在阅读本文之前,请先阅读(一)和(二)中的简单工厂模式和工厂方法模式. 1抽象工厂模式简介 抽象工厂 (Abstract Factroy) 模式:工具箱模式(kit).抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态,如下图. 图1.1 上图左边有一个工厂类的等级结构,右边有两个不同的产品等级结构,分别是产品A的等级结构和产品B的等级结构,工厂1和工厂2分别负责不同一个产品等级,同一个产品族的产品的生产.又例如下图: 图1.2 上图表示的是Button和Text两个不同产品的等级

JAVA设计模式之 状态模式【State Pattern】

一.概述 当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式.状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化.状态模式是一种对象行为型模式. 二.适用场景 用于解决系统中复杂对象的多种状态转换以及不同状态下行为的封装问题.简单说就是处理对象的多种状态及其相互转换. 三.UML类图 四.参与者 1>.AbstractState(抽象状态类): 在抽象状态类中定义申明了不同状态下的行为抽象方法,而由子类

Java设计模式——装饰者模式

JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式. 结构 图-装饰者模式结构图 Component : 定义一个对象接口,可以给这些对象动态地添加职责. interface Component {     public void operation(); } ConcreteComponent : 实现 Component 定义的接口. clas

Java设计模式之工厂模式(Factory模式)介绍(转载)

原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工厂.Java工厂模式举例等内容,需要的朋友可以参考下 工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经