您的位置:首页 > 编程语言 > Java开发

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

2017-03-30 14:51 246 查看
合成模式

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

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

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

一.UML示意图



二.组成部分

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

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

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

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

(一)、安全方式

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

[java] view
plain copy

package com.eekq.structure.composite.security;  

/* 

 * 抽象构件,物品 

 * */  

public interface IRes {  

    /**购物买单,示意性的商业方法*/  

    public void pay();  

}  

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

[java] view
plain copy

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.多个物品(树枝构件)

[java] view
plain copy

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.收银台买单

[java] view
plain copy

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. 抽象构件

[java] view
plain copy

package com.eekq.structure.composite.clarity;  

   

/* 

 * 抽象构件,物品 

 * */  

public interface IRes {  

    /**购物买单,示意性的商业方法*/  

    public void pay();  

   

    /**加入新的物品*/  

    public void addRes(IRes res);  

   

    /**放回物品*/  

    public void removeRes(IRes res);  

}  

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

[java] view
plain copy

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.收银台买单

 

[java] view
plain copy

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())时,在编译期不会有错,但在执行期会报错,这样不容易被发觉错误出在哪.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  23种设计模式