热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[19/04/26-星期五]GOF23_结构型模式(桥接模式、组合模式)

一、桥接模式(bridge)场景:商城系统中常见的商品分类,以电脑为例,首先想到使用多层继承结构。——台式机(联想台式机、戴尔台式机、神舟台式机)电脑——笔记

一、桥接模式(bridge)

场景:商城系统中常见的商品分类,以电脑为例,首先想到使用多层继承结构。

          —— 台式机(联想台式机、戴尔台式机、神舟台式机)

电脑    ——笔记本(联想笔记本、戴尔笔记本、神舟笔记本)

           ——平板电脑(联想pad、戴尔pad、神舟pad)

问题:(1)如果要增加一个新的电脑类型,则要增加各个品牌下的类。

           (2)如果要增加一个新的品牌,也要增加各种电脑类型的类

把另一个类的结构作为属性放在这个类中。

核心:处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联

好处:桥接模式可以取代多层继承的方案。 多层继承违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护的成本。

桥接模式极大的提高了系统可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统,符合开闭原则。

应用场景:

– JDBC驱动程序

– AWT中的Peer架构

– 银行日志管理:

• 格式分类:操作日志、交易日志、异常日志

• 距离分类:本地记录日志、异地记录日志

– 人力资源系统中的奖金计算模块:

• 奖金分类:个人奖金、团体奖金、激励奖金。

• 部门分类:人事部门、销售部门、研发部门。

– OA系统中的消息处理:

• 业务类型:普通消息、加急消息、特急消息

• 发送消息方式:系统内消息、手机短信、邮件

 

【不用桥接模式UML类图】

【代码】

/***
 * "电脑"接口 不用桥接模式
 */
package cn.sxt.bridge;

public interface Computer {
    void sale();

}

class Desktop implements Computer{
    public void sale() {
        System.out.println("销售台式机!");
    }
}
class Laptop implements Computer{
    public void sale() {
        System.out.println("销售笔记本!");
    }
}
class Pad implements Computer{
    public void sale() {
        System.out.println("销售平板电脑!");
    }
}

//联想系列
class LenovoDesktop extends Desktop{
    public void sale() {
        System.out.println("销售联想台式机!");
    }
}
class LenovoLaptop extends Laptop{
    public void sale() {
        System.out.println("销售联想笔记本!");
    }
}
class LenovoPad extends Pad{
    public void sale() {
        System.out.println("销售联想平板!");
    }
}
//神舟系列
class ShenZhouDesktop extends Desktop{
    public void sale() {
        System.out.println("销售神舟台式机!");
    }
}
class ShenZhouLaptop extends Laptop{
    public void sale() {
        System.out.println("销售神舟笔记本!");
    }
}
class ShenZhouPad extends Pad{
    public void sale() {
        System.out.println("销售神舟平板!");
    }
}

//戴尔系列
class DellDesktop extends Desktop{
    public void sale() {
        System.out.println("销售戴尔台式机!");
    }
}
class DellLaptop extends Laptop{
    public void sale() {
        System.out.println("销售戴尔笔记本!");
    }
}
class DellPad extends Pad{
    public void sale() {
        System.out.println("销售戴尔平板!");
    }
}

 

【使用桥接模式UML类图】

【代码】

/***
 * "品牌"接口 和各种具体品牌类,又一个维度,2个维度相互独立,x轴
 */
package cn.sxt.bridge;

public interface Brand {
    void sale();
}

class Lenovo implements Brand{
    @Override
    public void sale() {
        System.out.println("销售联想牌电脑");
    }
}

class Dell implements Brand{
    @Override
    public void sale() {
        System.out.println("销售戴尔牌电脑");
    }
}
//在这里,新加品牌“神舟”
class ShenZhou implements Brand{
    @Override
    public void sale() {
        System.out.println("销售神舟牌电脑");
    }
}

 

/**
 * 电脑类型,一个维度,y轴
 */
package cn.sxt.bridge;

public class Computer2 {
    protected Brand brand;//持有Brand类的引用,使电脑类Computer2 天然具有品牌类(Brand)的属性
    
    public Computer2(Brand b) {//构造器
        this.brand=b;
    }
    
    public void sale() {
        brand.sale();//调用的是Brand类中brand对象的sale方法
    }
}

class Desktop2 extends Computer2{
    public Desktop2 (Brand b) {
        super(b);
    }
    public void sale() {
        super.sale();
        System.out.println("销售台式机");    
    }
}
class Laptop2 extends Computer2{
    public Laptop2 (Brand b) {
        super(b);
    }
    public void sale() {
        super.sale();
        System.out.println("销售笔记本");    
    }
}

【客户】

/***
 * 客户端
 */
package cn.sxt.bridge;

public class Client {
    public static void main(String[] args) {
        //销售联想牌的笔记本电脑,用组合来代替继承,后期扩展很方便
        Computer2 c= new Laptop2(new Lenovo());
        c.sale();
        Computer2 c1= new Desktop2(new ShenZhou());
        c1.sale();
    }

}

 

二、组合模式(Composite、复合物)

场景:把部分和整体的关系用树形结构来表示,从而使客户端可以用统一的方式处理部分对象和整体对象。

核心:

– 抽象构件(Component)角色: 定义了叶子和容器构件的共同点

– 叶子(Leaf)构件角色:无子节点,叶子节点。

– 容器(Composite)构件角色: 有容器特征,可以包含子节点。非叶子节点

组合模式工作流程分析:

– 组合模式为处理树形结构提供了完美的解决方案,描述了如何将容器和叶子进行递归组合,使得用户在使用时可以一致性的对待容器和叶子。

– 当容器对象的指定方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员,并调用执行。其中,使用了递归调用的机制对整个结构进行处理。

 

开发中的应用场景:

– 操作系统的资源管理器

– GUI中的容器层次图

– XML文件解析

– OA系统中,组织结构的处理

– Junit单元测试框架:底层设计就是典型的组合模式,TestCase(叶子)、TestUnite(容器)、Test接口(抽象)

 

【类图】

 

 

【概念】

/***
 * 抽象组件,叶子节点和非叶节点的共同点。Component:组成部分、成分、部件
 */
package cn.sxt.composite;

public interface Component {
    void operation();

}

//叶子组件节点
interface Leaf extends Component{
    
}
//容器组件,非叶节点
interface Composite extends Component{
    void add (Component c);//增加节点
    void remove(Component c);//删除节点
    Component getChild(int index);//获得孩子节点
    
}

 

【叶子节点和非叶子节点】

/***
 * 抽象文件(AbstractFile)接口,相当于Component接口(抽象组件)
 */
package cn.sxt.composite;


import java.util.ArrayList;
import java.util.List;

public interface AbstractFile {
    void killVirus();
}

class ImageFile implements AbstractFile{//相当于叶子节点Leaf,单个文本中不能再包含其他文件
    private String name;
    
    public ImageFile(String name) {
        this.name=name;
    }
    @Override
    public void killVirus() {
        System.out.println("查杀图片文件:"+name);        
    }
}

class TextFile implements AbstractFile{
    private String name;
    
    public TextFile(String name) {
        this.name=name;
    }
    @Override
    public void killVirus() {
        System.out.println("查杀文本文件:"+name);        
    }
}

class VideoFile implements AbstractFile{
    private String name;
    
    public VideoFile(String name) {
        this.name=name;
    }
    @Override
    public void killVirus() {
        System.out.println("查杀视频文件:"+name);        
    }
}

class Folder implements AbstractFile{//Folder:文件夹 ,容器组件,非叶子节点
    private String name;
    //定义容器,用来存储子节点
    private List list =new ArrayList();
    
    public Folder(String name) {
        this.name=name;
    }
    
    public void add(AbstractFile file) {
        list.add(file);    
    }
    public void remove(AbstractFile file) {
        list.remove(file);    
    }
    public AbstractFile getChild(int index) {
        return list.get(index);
    }

    //杀毒
    public void killVirus() {//递归:自己调用自己
        System.out.println("对文件夹:"+name+",进行查杀。");
        for (AbstractFile absFile : list) {
            absFile.killVirus();
        }
    }
    
}

 

【客户端】

/**
 * 
 */
package cn.sxt.composite;


public class CLient {
    public static void main(String[] args) {
        AbstractFile f2,f3,f4,f5,f6;
        Folder f1=new Folder("古装剧收藏");
        f2=new ImageFile("SongYi.jpg");
        f3=new TextFile("SheDiao.txt");
        f4=new VideoFile("zhifou.mp4");
        f2.killVirus();
        
        f1.add(f2);
        f1.add(f3);
        f1.add(f4);
        Folder f11=new Folder("胡歌的古装剧");
        f5=new ImageFile("xianjian1.avi");
        f6=new TextFile("Shenhua.mp4");
        f11.add(f5);
        f11.add(f6);
        f1.add(f11);//文件夹套文件夹
        f1.killVirus();//无论是文件f2还是文件夹f1都是继承同一个AbstractFile接口中的killVirus()方法,只调用这个方法即可
        
        
    }

}

 


推荐阅读
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 点击上方“新机器视觉”,选择加”星标”或“置顶”重磅干货,第一时间送达很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间。去年有过一段时间的集中学习,做 ... [详细]
  • 获得要素图层通过UID获取1<summary>2获得要素图层UID获取(第一种方法)3&l ... [详细]
author-avatar
枇杷语1314
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有