java设计模式-组合模式详解

目录
  • 组合模式
    • Demo
    • 代码:
  • 总结

组合模式

组合模式(Composite Pattern)又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

  • 主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
  • 如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
  • 何时使用:

1.您想表示对象的部分-整体层次结构(树形结构)。

2.您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

  • 使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。
优点 缺点
高层模块调用简单,节点自由增加。 叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

文件夹-文件的树形结构一定不陌生,文件看作叶子结点(单个对象),文件夹看作中间结点(组合对象)。

组合模式使得用户对单个对象和组合对象的访问具有一致性,即让用户以一致的方式处理个别对象以及组合对象。避免在使用过程中区分开来,造成麻烦。

  • Component :组合中的对象声明接口,用于访问和管理Component子部件。
  • Leaf:单个/叶子对象,叶子结点没有子结点。
  • Composite:组合/容器对象,存储子部件和枝节点行为,实现与子部件有关操作,如增加(add)和删除(remove)等,list实现容器,容纳Component对象。

Demo

先来看看一般的写法:

当用户只满足一种折扣方案时,这种方法还能应对。

但精打细算的我们往往是同时满足多种折扣方案,这时就可以用组合模式,把这些单个折扣方案组合容纳起来,然后定义解决折扣冲突策略。实现单个对象和组合对象的统一,让调用者使用时不必在区分。

把组合对象CompositeDiscount定义成抽象类,SingleMinStrategy和MultipleStrategy继承它,表示解决冲突的策略,分别是取最小折扣和取折上折。

一般解决折扣冲突都是折上折,但商家往往更精明,推出互斥券之类的,即取最小折扣。也可以自定义其他折扣冲突策略。

涉及了点工厂模式和策略模式,DiscountFactory就是实例化Order类的属性DiscountStrategy的工厂,各种折扣策略实现同一接口。

代码:

public interface DiscountStrategy {
    public double getTotal(double price);
}
public class VIPDiscount implements DiscountStrategy {
    //95折
    @Override
    public double getTotal(double price) {
        return 0.95*price;
    }
}
public class ActivityDiscount implements DiscountStrategy{
    //9折
    @Override
    public double getTotal(double price) {
        return 0.9*price;
    }
}
public class StoreDiscount implements DiscountStrategy{
    //满500超出部分打6折
    @Override
    public double getTotal(double price) {
        return 500+0.6*(price-500);
    }
}
public abstract class CompositeDiscount implements DiscountStrategy {
    protected List<DiscountStrategy> strategies =new ArrayList(); //容器
    public void add(DiscountStrategy discountStrategy){ //添加叶子结点
        strategies.add(discountStrategy);
    }
    @Override
    public double getTotal(double price) {
        return price;
    }
}
//多种折扣选最低折扣
public class SingleMinStrategy extends CompositeDiscount {
    @Override
    public double getTotal(double price) {
        double rtn=price;
        for (DiscountStrategy s: strategies) {
            rtn=Math.min(rtn,s.getTotal(price));
        }
        return rtn;
    }
}
//多种折扣用折上折
public class MultipleStrategy extends CompositeDiscount {
    @Override
    public double getTotal(double price) {
        double rtn = price;
        for (DiscountStrategy s : strategies) {
            rtn = s.getTotal(rtn);
        }
        return rtn;
    }
}
public class DiscountFactory {
    public DiscountStrategy create(String type){ //工厂来创建相应策略
        //单一折扣策略
        if("ynn".equals(type))return new VIPDiscount();
        else if("nyn".equals(type))return new StoreDiscount();
        else if("nny".equals(type))return new ActivityDiscount();
        else{  //多种折扣策略
            CompositeDiscount compositeDiscount;
            System.out.println("请选择冲突解决方案:1.折上折 2.最低折");
            Scanner scanner=new Scanner(System.in);
            int type2=scanner.nextInt();
            if(type2==1){
                compositeDiscount=new MultipleStrategy();
            }
            else{
                compositeDiscount=new SingleMinStrategy();
            }
            if(type.charAt(1)=='y')compositeDiscount.add(new StoreDiscount());
            if(type.charAt(0)=='y')compositeDiscount.add(new VIPDiscount());
            if(type.charAt(2)=='y')compositeDiscount.add(new ActivityDiscount());
            return compositeDiscount;
        }
    }
}
public class Order {
    public double price;
    private String type;
    public DiscountStrategy discountStrategy;
    public Order(double price) {
        this.price=price;
    }
    public void display(){
        System.out.println("总价:"+price);
        System.out.println("是否是VIP?y/n");
        Scanner scanner=new Scanner(System.in);
        type=scanner.next();
        System.out.println("是否超过500?y/n");
        String tmp;
        tmp=scanner.next();
        type+=tmp;
        System.out.println("是否满足活动价?y/n");
        tmp=scanner.next();
        type+=tmp;
        DiscountFactory discountFactory=new DiscountFactory();
        double discountPrice=discountFactory.create(type).getTotal(price);
        System.out.println("优惠:"+(price-discountPrice));
        System.out.println("应付:"+discountPrice);
    }
}
public class Client {
    public static void main(String[] args) {
        Order order=new Order(620);
        order.display();
    }
}

运行结果:

这样一来,无论是单一折扣还是多种折扣,客户端使用时都是一个用法,不必区分和操心。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

时间: 2021-07-17

23种设计模式(10)java组合模式

23种设计模式第四篇:java组合模式 介绍 组合模式又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解藕. 组合模式可以优化处理递归或分级数据结构.有许多关于分级数据结构的例子,使得组合模式非常有用武之地. 类图 组成部分: Component: 为参加组合的对象声明一个公共接口, 不管是组合还是叶结点. Leaf: 在组合中表示叶子结点对象,叶子结点没有子结点. Composit

分析Java设计模式之组合模式

目录 一.概述 二. 模式定义 三. 模式结构 四. 模式实现 五. 模式优缺点 5.1.优点 5.2.缺点 六. 模式适用场景 七. 模式总结 一.概述 我们对于这个图片肯定会非常熟悉,这两幅图片我们都可以看做是一个文件结构,对于这样的结构我们称之为树形结构.在数据结构中我们了解到可以通过调用某个方法来遍历整个树,当我们找到某个叶子节点后,就可以对叶子节点进行相关的操作.我们可以将这颗树理解成一个大的容器,容器里面包含很多的成员对象,这些成员对象即可是容器对象也可以是叶子对象.但是由于容器对象

详细总结Java组合模式

一.前言 组合模式,又叫部分整体模式,是用于把一组相似的对象,当做单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式,它提供了修改相同对象组的方式. 二.介绍 意图: 将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 主要解决: 它在我么的属性结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样处理复杂元素,从而使得客户程序的复杂元素的内部结构解耦. 应

Java使用组合模式实现表示公司组织结构功能示例

本文实例讲述了Java使用组合模式实现表示公司组织结构功能.分享给大家供大家参考,具体如下: 一.模式定义 组合模式:将对象组合成树形结构以表示"部分一整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 二.组合模式举例 1 模式分析 我们借用公司组织结构图来说明这一模式. 经过分析后,我们得出该模式静态类图如下: 2 代码示例 2.1 建立员工抽象类 package com.demo.composite; /** * 职工类接口 * * @author * */

java实现Composite组合模式的实例代码

//20210121 写在前面:刚期末考试完,考了面向对象,里边儿有23个设计模式,我寻思着考完挨个儿实现一下,本文实现组合模式 组合模式核心思想类似文件夹的概念,构件树形结构,树形有叶子结点和文件夹结点,文件夹结点可以包含叶子结点和文件夹结点 分为两种模式 - 透明型:所有节点构造全部相同,但是由于叶子结点没有下层结点,所以其有些方法为空,会不安全 - 安全型:叶子结点和文件架节点构造不同,这样展示的时候需要判断节点属性,不方便调用,但是由于没有空方法,会很安全 透明型组合模式程序源代码: /

iOS应用开发中运用设计模式中的组合模式的实例解析

何为组合模式?     组合模式让我们可以把相同基类型的对象组合到树状结构中,其中父节点包含同类型的子节点.换句话说,这种树状结构形成"部分--整体"的层次结构.什么是"部分--整体"的层次结构呢?它是既包含对象的组合又包含叶节点的单个对象的一种层次结构.每个组合体包含的其他节点,可以是叶节点或者其他组合体.这种关系在这个层次结构中递归重复.因为每个组合或叶节点有相同的基类型,同样的操作可应用于它们中的每一个,而不必在客户端作类型检查.客户端对组合与叶节点进行操作时

JAVA设计模式之组合模式原理与用法详解

本文实例讲述了JAVA设计模式之组合模式.分享给大家供大家参考,具体如下: 组合(整体与部分关系)模式:将不同但是相关的对象组合成树形结构以实现"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性. * 模式角色组成: 1.Component对象: 是组合中的对象接口,是所有类共有的接口.是用于统一定义整体中的部分. 2.Leaf对象: 整体中的部分,没有下一级. 3.Composite对象: 用来存储子部件,在Component接口中实现与部分有关操作. 以公司构成

Ajax实现动态加载组合框的实例代码

一  province.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html> <head> <script type="text/javascript" language="javaScript"> var xmlHttp = false; //全局变量,

java实现事件委托模式的实例详解

java实现事件委托模式的实例详解 举例说明: 一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,与的是看电视(有点不合理) B类:放哨的学生,专门看老师的动向,如果老师进班了就立即通知大家. 如此就形成了一个需求,放哨的学生要通知所有玩的学生:老师来了,而不同的学生有不同的反应,有的马上把电视关闭,有的停止玩游戏. 设计的要求如下,让A类学生和B类学生完全解耦,即A类完全不知道B类的学生,却可以通知B类的学生. 代码及说明如下: Event 类,定义了一个事件类: pa

Java使用正则表达式(regex)匹配中文实例代码

只能输入中文 /** * 22.验证汉字 * 表达式 ^[\u4e00-\u9fa5]{0,}$ * 描述 只能汉字 * 匹配的例子 清清月儿 */ @Test public void a1() { Scanner sc = new Scanner(System.in); String input = sc.nextLine(); String regex = "^[\\u4e00-\\u9fa5]*$"; Matcher m = Pattern.compile(regex).matc

Java web的读取Excel简单实例代码

目录结构: Data.xls数据: 后台页面: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //System.out.println(this.getServletContext().getRealPath ("/")); try{ Workbook wb = Workbook.getWorkbook(

Java Web 简单的分页显示实例代码

本文通过两个方法:(1)计算总的页数. (2)查询指定页数据,实现简单的分页效果. 思路:首先得在 DAO 对象中提供分页查询的方法,在控制层调用该方法查到指定页的数据,在表示层通过 EL 表达式和 JSTL 将该页数据显示出来. 先给大家展示下效果图: 题外话:该分页显示是用 "表示层-控制层-DAO层-数据库"的设计思想实现的,有什么需要改进的地方大家提出来,共同学习进步.废话不多说了,开始进入主题,详细步骤如下所示: 1.DAO层-数据库 JDBCUtils 类用于打开和关闭数据

java 日期各种格式之间的相互转换实例代码

java 日期各种格式之间的相互转换实例代码 java日期各种格式之间的相互转换,直接调用静态方法 实例代码: java日期各种格式之间的相互转换,直接调用静态方法 package com.hxhk.cc.util; import java.text.SimpleDateFormat; import java.util.Date; import com.lowagie.text.pdf.codec.postscript.ParseException; public class DateUtil

java 文件大数据Excel下载实例代码

java 文件大数据Excel下载实例代码 excel可以用xml表示.故可以以此来实现边写边下载文件 package com.tydic.qop.controller; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.I

Java 大小写最快转换方式实例代码

Java 大小写最快转换方式实例代码          这里直接给出实现代码,在代码中注释都很清楚,不多做介绍. Java代码 package io.mycat; import java.util.stream.IntStream; /** * 小写字母的 'a'=97 大写字母 A=65 更好相差32利用这个差进行大小写转换 * @author : Hpgary * @date : 2017年5月3日 10:26:26 * @mail: hpgary@qq.com * */ public cl