第五个设计模式:合成模式

第五个设计模式:合成模式

合成模式 把部分和整体关系用树结构表示,是属于对象的结构模式。 合成模式 要对组合的对象进行管理,所以在一定位置给予对象的相关管理方法,如: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 自动生成方法存根
        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.多个物品 (树枝构件)
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 {
    /**
      * @param args
      */
    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 {
    /**
      * @param args
      */
    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())时,在编译期不会有错,但在执行期会报错,这样不容易被发觉错误出在哪.
作者:飞行鱼 QQ:6868861 推荐J2EE群:7715552
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本教程为授权出品教程1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习下设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括:设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)。2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值