zoukankan      html  css  js  c++  java
  • 设计模式之组合模式学习理解

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

    这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

    介绍

    意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

    主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

    何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

    如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。

    关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。

    应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作树、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。

    优点: 1、高层模块调用简单。 2、节点自由增加。

    缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

    使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。

    注意事项:定义时为具体类。

    下面一个例子是从项目里面剥离出来的,

    车载gps服务商可以用到组合模式
    * 特点:
    * 1.有层级关系
    * 2.各级服务商都有相同的操作 为客户(假设是汽车租赁公司)安装车载gps终端,同一个客户,假设名字叫讯芯汽车租赁公司,它可能在宿迁有车子要安装gps,在扬州也有车子要安装gps,那他不管去到哪一级服务商那儿去安装,只要每安装完成一台gps终端,会自动计费到系统,最后再 统一缴费或者从预付费里扣除。

    抽象服务商类

     1 /**
     2  * 抽象服务商类
     3  * @author ko
     4  *
     5  */
     6 public abstract class AbstractFacilitator {
     7 
     8     protected String name;
     9     protected String pwd;
    10     protected String address;
    11     
    12     protected List<AbstractFacilitator> subordinate;// 下级服务商集合
    13 
    14     public AbstractFacilitator(String name, String pwd, String address) {
    15         this.name = name;
    16         this.pwd = pwd;
    17         this.address = address;
    18         subordinate = new ArrayList<>();
    19     }
    20     
    21     /**
    22      * 每个服务商都有的业务操作(给客户安装gps终端)
    23      * @param cusName 客户名(汽车租赁公司名)
    24      * @param gpsNum 要安装的gps台数
    25      */
    26     public abstract void installGpsTerminal(String cusName,int gpsNum);
    27     
    28     // 增加
    29     public abstract void add(AbstractFacilitator f);
    30     
    31     // 删除
    32     public abstract void remove(AbstractFacilitator f);
    33     
    34     // 获取下属服务商集合(只是下一级,不是所有的下级,那样的话需要递归)
    35     public abstract List<AbstractFacilitator> getSubordinate();
    36     
    37 }

    车载gps服务商类

     1 /**
     2  * 车载gps服务商
     3  * 特点:
     4  *         1.有层级关系
     5  *         2.各级服务商都有相同的操作 为客户(假设是汽车租赁公司)安装车载gps终端,同一个客户,假设名字叫讯芯汽车租赁公司,它可能在宿迁有车子
     6  *         要安装gps,在扬州也有车子要安装gps,那他不管去到哪一级服务商那儿去安装,只要每安装完成一台gps终端,会自动计费到系统,最后再
     7  *         统一缴费或者从预付费里扣除
     8  * @author ko
     9  *
    10  */
    11 public class GpsFacilitator extends AbstractFacilitator {
    12 
    13 
    14     public GpsFacilitator(String name, String pwd, String address) {
    15         super(name, pwd, address);
    16     }
    17 
    18     @Override
    19     public void installGpsTerminal(String cusName, int gpsNum) {
    20         try {
    21             Thread.sleep((new Random().nextInt(5)+1)*100*gpsNum);// 模拟安装gps耗时
    22         } catch (InterruptedException e) {
    23             e.printStackTrace();
    24         }
    25         System.out.println("服务商 "+name+"为"+cusName+"安装了"+gpsNum+"台gps终端");
    26         double surplus = TollCharge.preDeposit.get(cusName).subtract(TollCharge.unitPrice.multiply(new BigDecimal(gpsNum))).doubleValue();
    27         System.out.println("本次扣费:"+TollCharge.unitPrice.multiply(new BigDecimal(gpsNum)).doubleValue()+"元,"+cusName+"剩余:"+surplus+"元");
    28         
    29         // 重置客户预存的钱
    30         TollCharge.preDeposit.put("xunxin", new BigDecimal(surplus));
    31     }
    32 
    33     @Override
    34     public void add(AbstractFacilitator f) {
    35         subordinate.add(f);
    36     }
    37 
    38     @Override
    39     public void remove(AbstractFacilitator f) {
    40         subordinate.remove(f);
    41     }
    42 
    43     @Override
    44     public List<AbstractFacilitator> getSubordinate() {
    45         return subordinate;
    46     }
    47     
    48     
    49     
    50 }

    收费管理类

     1 /**
     2  * 收费管理
     3  * @author ko
     4  *
     5  */
     6 public class TollCharge {
     7 
     8     public static final BigDecimal unitPrice = new BigDecimal(20);
     9     
    10     public static Map<String, BigDecimal> preDeposit = new HashMap<>();// 客户(汽车租赁公司)预存的钱
    11     
    12     static{
    13         preDeposit.put("xunxin", new BigDecimal(10000));// 讯芯预存的钱
    14         // 。。。。
    15     }
    16 }

    测试类

     1 public class Test {
     2     public static void main(String[] args) {
     3         // 江苏总服务商
     4         GpsFacilitator jiangsu_gps = new GpsFacilitator("gps jiangsu", "123456", "Nanjing city of Jiangsu Province");
     5         // 宿迁分服务商
     6         GpsFacilitator suqian_gps = new GpsFacilitator("gps suqian", "123456", "Suqian city of Jiangsu Province");
     7         // 扬州分服务商
     8         GpsFacilitator yangzhou_gps = new GpsFacilitator("gps yangzhou", "123456", "Yangzhou city of Jiangsu Province");
     9         // 宿迁宿城分服务商
    10         GpsFacilitator sucheng_gps = new GpsFacilitator("gps sucheng", "123456", "Sucheng District of Jiangsu Province");
    11         // 宿迁宿豫分服务商
    12         GpsFacilitator suyu_gps = new GpsFacilitator("gps suyu", "123456", "Suyu District of Jiangsu Province");
    13         // 扬州高邮分服务商
    14         GpsFacilitator gaoyou_gps = new GpsFacilitator("gps gaoyou", "123456", "Gaoyou District of Jiangsu Province");
    15         // 扬州邗江分服务商
    16         GpsFacilitator hanjiang_gps = new GpsFacilitator("gps hanjiang", "123456", "Hanjiang District of Jiangsu Province");
    17         
    18         // 添加子服务商
    19         jiangsu_gps.add(suqian_gps);
    20         jiangsu_gps.add(yangzhou_gps);
    21         
    22         suqian_gps.add(sucheng_gps);
    23         suqian_gps.add(suyu_gps);
    24         yangzhou_gps.add(gaoyou_gps);
    25         yangzhou_gps.add(hanjiang_gps);
    26         
    27         jiangsu_gps.installGpsTerminal("xunxin", 33);// 江苏总服务商给讯芯安装33台gps终端
    28         suqian_gps.installGpsTerminal("xunxin", 25);// 宿迁分服务商给讯芯安装25台gps终端
    29         hanjiang_gps.installGpsTerminal("xunxin", 15);// 扬州邗江分服务商给讯芯安装15台gps终端
    30         
    31         System.out.println("江苏总服务商有下属服务商:"+jiangsu_gps.getSubordinate().size()+"个");
    32         jiangsu_gps.remove(suqian_gps);// 移除宿迁分服务商
    33         System.out.println("江苏总服务商有下属服务商:"+jiangsu_gps.getSubordinate().size()+"个");
    34     }
    35 }

    打印结果

    服务商 gps jiangsu为xunxin安装了33台gps终端
    本次扣费:660.0元,xunxin剩余:9340.0元
    服务商 gps suqian为xunxin安装了25台gps终端
    本次扣费:500.0元,xunxin剩余:8840.0元
    服务商 gps hanjiang为xunxin安装了15台gps终端
    本次扣费:300.0元,xunxin剩余:8540.0元
    江苏总服务商有下属服务商:2个
    江苏总服务商有下属服务商:1个
    
  • 相关阅读:
    黄页js-sdk开发总结分享
    最近的shell脚本(updating)
    nginx location 的配置
    nodejs 的安全
    paypal之nodejs 框架 Kraken-js 源码分析
    nodejs express 框架解密5-视图
    nodejs express 框架解密4-路由
    nodejs express 框架解密3-中间件模块
    nodejs express 框架解密2-如何创建一个app
    nodejs express 框架解密1-总体结构
  • 原文地址:https://www.cnblogs.com/shamo89/p/7155617.html
Copyright © 2011-2022 走看看