Java设计模式之五 ----- 外观模式和装饰器模式
前言
在上一篇中我们学习了结构型模式的适配器模式和桥接模式。本篇则来学习下结构型模式的外观模式和装饰器模式。
外观模式
简介
外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
简单的来说就是对外提供一个简单接口,隐藏实现的逻辑。比如常用电脑的电源键,我们只需按电源键,就可以让它启动或者关闭,无需知道它是怎么启动的(启动CPU、启动内存、启动硬盘),怎么关闭的(关闭硬盘、关闭内存、关闭CPU);
这里我们还是可以用电脑玩游戏的例子来对外观模式进行简单的讲解。
电脑上有一些网络游戏,分别是DNF、LOL和WOW,我们只需双击电脑上的图标就可以启动并玩游戏了,无需关心游戏是怎么启动和运行的了。
需要实现的步骤如下:
- 建立游戏的接口;
 - 建立LOL、DNF和WOW的类并实现游戏的接口;
 - 定义一个外观类,提供给客户端调用。
 - 调用外观类。
 
代码示例:
interface Game{
    void play();
}
class DNF implements Game{
    @Override
    public void play() {
        System.out.println("正在玩DNF...");
    }
}
class LOL implements Game{
    @Override
    public void play() {
        System.out.println("正在玩LOL...");
    }
}
class WOW implements Game{
    @Override
    public void play() {
        System.out.println("正在玩WOW...");
    }
}
class Computer{
    private Game dnf;
    private Game lol;
    private Game wow;
    public Computer() {
        dnf=new DNF();
        lol=new LOL();
        wow=new WOW();
    }
    public void playDNF(){
        dnf.play();
    }
    public void playLOL(){
        lol.play();
    }
    public void playWOW(){
        wow.play();
    }
}
public static void main(String[] args) {
        Computer computer=new Computer();
        computer.playDNF();
        computer.playLOL();
        computer.playWOW();
    }
运行结果:
    正在玩DNF...
    正在玩LOL...
    正在玩WOW...
在上述代码示例中,我们在想玩游戏的时候,只用实例化外观类调用其中的游戏方法即可,无需关心游戏是怎么启动和运行的。而且每个游戏之间也相互独立,互不影响,不会因为某个游戏玩不了导致其它的游戏也无法运行。其实感觉外观模式和我们平时使用接口很相像,都是对外提供接口,并不需要关心是如何实现的。
外观模式的优点:
降低了耦合,从某种方面来说也提升了安全性。
外观模式的缺点:
不符合开闭原则,不易更改。
使用场景
系统中有多个复杂的模块或者子系统的时候。
装饰器模式
简介
装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
装饰器模式,顾名思义,也就是把某个东西进行装饰起来,让它可以提供一些额外的功能。比如对人进行装饰,做不同的事情的时候穿上不同的服装。比如穿上球衣是准备去打球,穿上泳衣是准备去游泳之类的。
装饰器模式可以动态地给一个对象添加一些额外的职责。
这里我们依旧用一个示例来进行说明。
在现在的玩具模型中,有两种模型很受欢迎,高达(GUNDAM)模型和扎古(MrGu)模型,在我们拼接模型的时候,一般都是先将模型拼接好,然后再来添加一些额外的配件,比如武器。在这里我们在拼接好高达(GUNDAM)模型和扎古(MrGu)模型之后,给它们装上各自的武器。
具体实现的步骤如下:
- 创建一个抽象构件的模型接口,有组装这个方法;
 - 创建具体构件的类(GUNDAM类和MrGu类),并实现上述的模型接口;
 - 定义一个装饰器,用于接受客户端的请求,并根据客户端的请求进行相应的调用;
 - 定义个具体实现装饰的类,用于给对象添加相应的功能。
 
代码示例:
interface Model{
    void  assemble();
}
class GUNDAM implements Model{
    @Override
    public void  assemble() {
        System.out.println("组装一个高达模型");
    }
}
class MrGu implements Model{
    @Override
    public void  assemble() {
        System.out.println("组装一个扎古模型");
    }
}
abstract class  AddExtra implements Model{
    protected  Model model;
    public AddExtra(Model model){
        this.model=model;
    }
    public  void assemble(){
        model.assemble();
    }
}
class LightSaber extends AddExtra{
    public LightSaber(Model model) {
        super(model);
    }
    public  void assemble(){
        model.assemble();
        addLightSaber();
    }
    public void addLightSaber(){
        System.out.println("添加光剑");
    }
}
class RocketLauncher extends AddExtra{
    public RocketLauncher(Model model) {
        super(model);
    }
    public  void assemble(){
        model.assemble();
        addRocketLauncher();
    }
    public void addRocketLauncher(){
        System.out.println("添加火箭筒");
    }
}
public static void main(String[] args) {
        Model gundam=new GUNDAM();
        Model mrgu=new MrGu();
        gundam.assemble();
        mrgu.assemble();
        Model gModel=new LightSaber(new GUNDAM());
        gModel.assemble();
        Model mModel=new RocketLauncher(new MrGu());
        mModel.assemble();
}
运行结果:
    组装一个高达模型
    组装一个扎古模型
    组装一个高达模型
    添加光剑
    组装一个扎古模型
    添加火箭筒
在上述的代码中,我们如果只想组装高达或这扎古的模型的话,可以直接实例化模型类,调用其中的方法即可。假若需要在组装模型的时候,添加一个武器,只需通过装饰器的类进行相应添加相应的功能即可。
通过这个示例,我们发现,在使用装饰器模式的时候,可以对一些类进行扩展,并且不影响之前的功能,提升了灵活度。
装饰器模式的优点:
装饰类和被装饰类可以独立发展,耦合度低,易于扩展,灵活方便。
装饰器模式的缺点:
过多的对某个类进行装饰,会增加复杂度。
使用场景
原型不变,动态增加一些功能的时候。
Java设计模式之五 ----- 外观模式和装饰器模式的更多相关文章
- 深入探索Java设计模式(三)之装饰器模式
		
装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...
 - Java设计模式(七)Decorate装饰器模式
		
一.场景描述 (一)问题 系统中最初使用Crystal Report(水晶报表)工具生成报表,并将报表发送给客户端查看,此时定义一CrystalReport工具类即可完成水晶报表的生成工作. 后续报表 ...
 - Java设计模式之(七)——装饰器模式
		
1.什么是装饰器模式? Attach additional responsibilities to an object dynamically keeping the same interface.D ...
 - Java进阶篇设计模式之五-----外观模式和装饰器模式
		
前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...
 - Java 设计模式系列(八)装饰者模式
		
Java 设计模式系列(八)装饰者模式 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案.Decorator 或 Wrapper 一.装饰模 ...
 - IOS设计模式之二(门面模式,装饰器模式)
		
本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq) ...
 - 面向对象程序设计(OOP设计模式)-结构型模式之装饰器模式的应用与实现
		
课程名称:程序设计方法学 实验4:OOP设计模式-结构型模式的应用与实现 时间:2015年11月18日星期三,第3.4节 地点:理1#208 一.实验目的 加深对结构型设计模式的理解以及在开发中的实际 ...
 - 涉及模式之    装饰器模式详解(与IO不解的情缘)
		
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...
 - 聊聊模板方法模式,装饰器模式以及AOP
		
在软件系统设计的时候,我们需要把一个大的系统按照业务功能进行拆分,做到高内聚.低耦合. 但是呢,拆分之后会产生一些通用性的东西,比如日志,安全,事务,性能统计等,这些非功能性需求,横跨多个模块.最lo ...
 
随机推荐
- System.Action的使用(lambda 表达式)
			
对于Action的使用方法使用如下: namespace ConsoleApp1 { class Program { static void Main(string[] args) { string ...
 - MRTG在Windows平台的安装及使用
			
MRTG (Multi Router Traffic Grapher)是一款监控网络流量负载的免费软件,目前利用MRTG已经开发出了各式各样的统计系统: 1.系统资源负载统计,例如:磁盘空间.CPU负 ...
 - spring-boot-2.0.3启动源码篇二 - run方法(一)之SpringApplicationRunListener
			
前言 Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,争取不让大家每周的期望落空.一周之中可 ...
 - JavaWeb学习 (五)————Servlet(一)
			
一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...
 - 身份认证与加密浅谈(PKI)
			
利用PKI体系解决私密文件传输中一系列问题的大体思路 背景:现有A用户和B用户之间想加密传输一些秘密文件,通过什么样的技术可以确保A和B传输数据的安全性?方案:采用对称秘钥对数据进行加密传输(对称加密 ...
 - .NET常用开发工具整理
			
版本控制和项目管理工具 VisualSVN和AnkhSVN:两款在Visual Studio中管理Subversion的插件.. NuGet和NuGetPackageExplorer:一组用于自动执行 ...
 - 浅谈websocket和c# socket(新手篇)
			
周末放假没带电脑所以今天分享质量不高,手机没有那些样式看起来可能没有那么方便,今天主要分享一下websocket. (赶紧拿小本本记下来) websocket 你发现是一个组合单词web socket ...
 - [PHP] 数据结构-输出链表倒数第k个结点PHP实现
			
输入一个链表,输出该链表中倒数第k个结点.第一个指针走(k-1)步,到达第k个节点,两个指针同时往后移动,当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了 <?php clas ...
 - Java中变量之局部变量、本类成员变量、父类成员变量的访问方法
			
变量:局部变量.本类成员变量.父类成员变量 如何访问:如果变量名相同,则采用就近原则,哪个变量离所要调用的访问最近,那就么就输出,优先顺序为:局部变量 > 本类成员变量 > 父类成员变量 ...
 - Matlab adaptive quadrature
			
% script to perform adaptive quadrature clear all, close all global pts % function to be integrated ...