`

设计模式 -- 装饰模式

阅读更多

 

Decorator Pattern装饰模式

装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

装饰,让我们想到了房子的装修、人的打扮、手机装饰等等,但是,不管怎么装修,房子还是那个房子、墙还是那堵墙,人还是那个人,脸还是那张脸;手机还是那部手机,屏幕还是那个屏幕,只是给人的感觉变了而已。

如果拿手机来说,我们买了手机后,都会给手机贴膜、安个吊坠、装个边框什么的,下面我们看看我们最常用的手机是如何贴膜的:


 

 

public class Phone {
    //构造方法
    public Phone(String name) {
        this.name = name;
    }
    //名称
private String name;
//贴膜
    public void film(){
        System.out.print(" 贴膜 "); 
}
//最后的外观
    public void exterior(){
        System.out.println(" 手机:"+ name + "的样子!"); 
    }
    //getter & setter
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

 

 

public class PhoneTest {
    public static void main(String[] args) {
        Phone p = new Phone("Iphone5");//一台Iphone5
        p.film();       //贴膜
        p.exterior();   //我们看到的样子
    }
}
 

 

 

这样设计是满足了要求,可是大家都知道,手机装饰有很多种,除了贴膜,还有吊坠、边框、后盖、贴纸….等等,难道新需求来的时候,去修改Phone这个类吗?

根据我们的设计原则:“只对扩展开放,对修改关闭”。就是根据变化去设计一个程序,以后有变化的时候,之扩展我们的程序就行了,不需要修改原来的程序。这就是设计模式的精髓所在。

根据以上的例子,我们要考虑,手机装饰随时可能变化,当你逛街时、浏览某个网站时,看到一款比较新奇的手机配件,也许你会更换装饰了!

我们可能想到了接口:把手机的装饰用一个接口来表示:让所有手机配件来继承这个接口:

 

 


 

 

 

//手机

public class Phone {
    //构造方法
    public Phone(String name) {
        this.name = name;
    }
    //名称
    private String name;
    //外观
    private List<Accessories> accessories = new ArrayList<Accessories>();
//   外观展示
    public void exterior(){
        for(Accessories accessorie : accessories){
            accessorie.exterior();
        }
        System.out.println(" 手机:"+ name + "的样子!");
    }
    //getter & setter
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Accessories> getAccessories() {
        return accessories;
    }
    public void setAccessories(List<Accessories> accessories) {
        this.accessories = accessories;
    }
}
 

 

 

//配件接口
public interface Accessories {
    void exterior();
} 
//贴膜
public class Film implements Accessories {
    public void exterior() {
        System.out.print(" 贴膜 "); 
    }
}

 

 

 //金属边框
public class MetalFrame implements Accessories {
    public void exterior() {
        System.out.print(" 金属边框 "); 
    }
}
 

 

//手机测试
public class PhoneTest {
    public static void main(String[] args) {
        Phone p = new Phone("Iphone5");//一台Iphone5
        //配件
        Accessories a = new Film();
        Accessories b = new MetalFrame();
        List<Accessories> l = new ArrayList<Accessories>();
        l.add(a);
        l.add(b);
        p.setAccessories(l);
//        外观展示
        p.exterior();
    }
}
 

 

 

这样似乎解决了问题,可是代码看起来非常复杂,特别是配件在装饰的时候,都要装到配件列表中。有没有更简洁的方式呢?

好吧,还是让我们用装饰模式优雅的解决这个问题吧:

 先看类图:

 


 

 

代码如下:

 

 

//手机接口
public interface Phone {
    public void exterior();
}
 

 

 

//具体的对象  --实现了手机接口
public class Iphone5 implements Phone {
    public void exterior() {
        System.out.print("Iphone5外观展示!"); 
    }
}

 //手机配件抽象类 ---同样实现手机接口

 

public abstract class Accessories implements Phone {
    //要装饰的对象 -- 手机
    private Phone phone;
    public void setPhone(Phone phone) {
        this.phone = phone;
    }
    //调用传入的Phone的exterior方法
    public void exterior() {
        if(phone != null){
            phone.exterior();
        }
    }
}
 

 

//具体装饰类:贴膜  -- 继承自配件类
public class Film extends Accessories {
//    重写父类中的外观展示方法,
//    在父类方法调用前加入自己的处理逻辑
    public void exterior() {
        System.out.print(" 贴膜 "); 
        super.exterior();
    }
}
 

 

 

//具体装饰:金属边框 – 继承自配件类
public class MetalFrame extends Accessories {
//  重写父类中的外观展示方法
//  在父类方法调用前加入自己的处理逻辑
    public void exterior() {
        System.out.print(" 金属边框 ");
        super.exterior();
    }
}
 

 

//代码测试
public class PhoneTest {
    public static void main(String[] args) {
//      一台Iphone5
        Iphone5 iphone5 = new Iphone5();
        //配件
        Film film = new Film();
        MetalFrame metalFrame = new MetalFrame();
//        外观展示
        film.setPhone(iphone5);
        metalFrame.setPhone(film);
        metalFrame.exterior();
    }
}
 

 

      是不是感觉代码更加简洁了,而且也更加灵活了。这是装饰模式在程序设计中发挥的重要作用。

      如果还不明白,我们可以举一个非常简单的例子,我们都吃过火锅,比如呷哺火锅,火锅点餐系统就是你点一份锅底,然后选择几份配菜,配菜可以随便点、而且可以点多份,锅底就一个,到结账的时候要知道点了那些东西,然后得花多少钱。根据这个需求,我们设计的时候用装饰模式来解决:

         建立一个食品接口,有一个获得食品名称的方法,一个计算价格的方法和另外一个通过传入其它食品计算价格的方法,然后具体对象是锅底,因为菜都是在锅底里面涮的,没有锅底肯定不行,而配菜是跟随锅底随意搭配的,配菜可以多点,而且可以点多份。建一个锅底类,给出具体名称和具体价格,和一个配菜抽象类,让锅底类和配菜都继承这个食品接口,然后让具体的配菜都继承配菜类,在配菜里给出配菜具体名称和具体价格。类图如下:


 

 

 

这样设计的好处是锅底的配菜能随意搭配,可多选可复选,而且以后如果增加另外一种锅底的时候,只需要去继承这个食品接口就可以了,配菜在扩展的时候只需要把新上市的蔬菜去继承配菜就行了,并不需要去更改以前写好的代码,这就遵循了设计原则的:“针对接口编程”和“对扩展开放,对修改关闭”的原则了。看看下面的代码,让我们开始点餐吧:

 

 

 

//食品接口
public interface Food {
    String getName();
    int price();
    int price(Food food);
}
 

 

//配菜抽象类
public abstract class Materials implements Food {
    public abstract String getName();
}
 

 

 

//锅底类—具体对象
public class Spicy implements Food {
    private String name;
    //构造方法
    public Spicy(String name){
        this.name = name;
    }
    //食品名称
    public String getName(){
        return name;
    }
    //价格
    public int price() {
        return 15;
    }
    public int price(Food food) {
        return food.price() + 15;
    }
}
 

 

 

//粉丝  --继承自配菜
public class Fans extends Materials {
    private Food food;
    //构造方法
    public Fans(Food food) {
        this.food = food;
    }
    public String getName() {
        return food.getName() + ",粉丝";
    }
    public int price() {
        return food.price() + 3;
    }
    public int price(Food food) {
        return food.price() + 3;
    }
}
 

 

 

//白菜类 – 继承自配菜
public class Cabbage extends Materials {
    private Food food;
    //构造方法
    public Cabbage(Food food) {
        this.food = food;
    }
    public String getName() {
        return food.getName() + ",白菜";
    }
    //白菜价格
    public int price() {
        return food.price() + 2;
    }
    //
    public int price(Food food) {
        return food.price() + 2;
    }
}
 

 

//牛肉类 – 继承自配菜
public class Beef extends Materials {
    private Food food;
    //构造方法
    public Beef(Food food) {
        this.food = food;
    }
    public String getName() {
        return food.getName() + ",牛肉";
    }
    public int price() {
        return food.price() + 10;
    }
    public int price(Food foods) {
        return foods.price() + 10;
    }
}
 

 

 

//五花肉类 – 继承自配菜
public class Pork extends Materials {
    private Food food;
    //构造方法
    public Pork(Food food) {
        this.food = food;
    }
    public String getName() {
        return food.getName() + ",五花肉";
    }
    public int price() {
        return food.price() + 8;
    }
    public int price(Food food) {
        return food.price() + 8;
    }
}
 

 

 

//豆皮类 – 继承自配菜类
public class Yuba extends Materials {
    private Food food;
    //构造方法
    public Yuba(Food food) {
        this.food = food;
    }
    public String getName() {
        return food.getName() + ",豆皮";
    }
    public int price() {
        return food.price() + 5;
    }
    public int price(Food foods) {
        return foods.price() + 5;
    }
}

 

 

 

//测试类
public class FoodTest {
    public static void main(String[] args) {
//      香辣锅底的点餐
        Spicy spicy = new Spicy("香辣锅底");
        Fans fans = new Fans(spicy);
        Yuba yuba = new Yuba(fans);
        Beef beef = new Beef(yuba);
        Cabbage cabbage = new Cabbage(beef);
        System.out.println( "您要点的菜是:" + cabbage.getName() 
+ ",合计:" + cabbage.price()+ "元。");
        
//      清汤锅底的点餐
        Spicy spicy2 = new Spicy("清汤锅底");
        Pork pork = new Pork(spicy2);
        Fans fans2 = new Fans(pork);
        Fans fans3 = new Fans(fans2);
        Cabbage cabbage2 = new Cabbage(fans3);
        System.out.println( "您要点的菜是:" + cabbage2.getName() 
+ ",合计:" + cabbage2.price()+ "元。");
    }
}

 

 

看看装饰模式的定义:动态的给一共对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

         在看看我们的程序,锅底对象可以动态的添加配菜,并且能动态的计算出当前点餐的价格。比起生成一个单独配菜的子类然后计算价格更加灵活。

  • 大小: 2.7 KB
  • 大小: 12.3 KB
  • 大小: 16.4 KB
  • 大小: 30.7 KB
分享到:
评论

相关推荐

    设计模式--装饰模式

    装饰模式(Decorator Pattern)是一种结构型设计模式,其主要目的是在不改变对象自身的基础上,在运行时为对象添加新的行为或属性。它通过包装原有对象,而不是通过继承来扩展功能,从而提供了更大的灵活性,避免了...

    23种设计模式--装饰模式

    装饰模式是一种结构型设计模式,它是面向对象设计中用来动态添加或修改对象功能的一种方法。在软件工程中,装饰模式允许我们向一个现有的对象添加新的行为或职责,同时又不改变其原有的结构,从而实现对类的功能扩展...

    C++设计模式--基于Qt4开源跨平台开发框架

    《C++设计模式--基于Qt4开源跨平台开发框架》一书主要探讨了如何在C++编程中利用设计模式,并结合Qt4框架进行高效的跨平台应用开发。设计模式是软件工程中的重要概念,它们是经过时间和实践验证的解决特定问题的模板...

    设计模式--装饰模式(讲解及其实现代码)

    装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或职责,而无需修改原有类的代码。这种模式的核心在于通过包装一个已有对象,来扩展其功能,而不是通过继承来实现。装饰模式是面向对象设计...

    设计模式--装饰者模式java例子

    装饰者模式是软件设计模式中的一种结构型模式,它的主要目的是动态地给对象添加新的功能,而无需修改原有代码。在Java中,装饰者模式通常通过继承和组合来实现,它提供了一种比继承更灵活的方式来扩展对象的功能。...

    JAVA-设计模式-结构型模式-装饰模式

    JAVA-设计模式-结构型模式-装饰模式

    c++设计模式-结构型模式-装饰器模式

    c++设计模式-结构型模式-装饰器模式;QT工程;c++简单源码; 装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

    设计模式-Java语言中的应用

    通过阅读《设计模式-Java语言中的应用》,读者不仅可以掌握设计模式的基本概念和原理,还能学习到如何在实际项目中选择合适的设计模式,以及如何优雅地在Java代码中实现这些模式。这将有助于提升开发者的编程技巧,...

    C++设计模式-基于QT4开源跨平台开发框架 源码

    设计模式分为三大类:创建型模式(如单例、工厂方法、抽象工厂)、结构型模式(如代理、装饰器、适配器)和行为型模式(如观察者、策略、命令)。这些模式都是在特定上下文中解决设计问题的模板,它们可以提高代码的...

    java设计模式---诙谐易懂版

    根据给定文件内容,以下是关于Java设计模式的知识点说明: 1. 策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时选择算法的行为。策略模式的意图是定义一系列算法,将每个算法封装起来,并使它们可以...

    设计模式 - 装饰模式(C++实例)

    装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在软件工程中非常常见,因为它提供了灵活性,使得我们可以独立于对象的组合来扩展功能。 在C++中,装饰...

    设计模式专题之(七)装饰模式---设计模式装饰模式示例代码(python--c++)

    装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或职责,同时保持对象的接口不变。这种模式使得我们可以在不修改原有代码的基础上,通过组合不同的装饰来扩展对象的功能,实现了代码的高可...

    设计模式-装饰者模式

    在“设计模式—装饰者模式”中,我们将深入探讨这个模式的概念、实现方式以及实际应用。 装饰者模式的核心概念在于“装饰”(Decorator)和“组件”(Component)。组件是被装饰的基本对象,它可以是接口或者抽象类...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 装饰模式(Decorator):动态地给一个对象添加一些额外的职责。 - 享元模式(Flyweight):使用共享对象,有效地支持大量细粒度的对象。 3. **行为型模式**:这类模式关注对象之间的责任分配。 - 责任链模式...

    设计模式---装饰者模式

    装饰者模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或职责,而无需修改对象的源代码或创建子类。这种模式的核心思想是通过将对象封装在一个装饰器对象内,来扩展对象的功能,同时保持原有接口的不变...

    设计模式 - 装饰者模式.rar

    装饰者模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或职责,而无需修改对象本身。这种模式的核心思想是通过将对象包装在一个装饰类中来扩展功能,而不是通过继承。以下是对装饰者模式的详细阐述: ...

    java常用设计模式-装饰器模式

    Java 设计模式 - 装饰器模式 装饰器模式(Decorator Pattern)是一种结构性设计模式,它允许您在不影响同一类的其他对象的行为的情况下,静态或动态地向单个对象添加行为。该模式非常有用,当您想要在运行时添加或...

    Java设计模式----通俗易懂版

    这个资源"Java设计模式----通俗易懂版"显然是一个专门针对初学者或需要深入理解设计模式的开发者编写的指南。作者以形象生动的例子解释了23种经典的Java设计模式,使得复杂的概念变得更加易于理解。 首先,我们要...

    软件设计模式--填空题+简答题(复习7).rar

    2. **设计模式分类**:设计模式通常分为三类:创建型模式(如工厂方法、抽象工厂、单例、建造者、原型)、结构型模式(如适配器、桥接、装饰、组合、代理、外观、享元)和行为型模式(如责任链、命令、解释器、迭代...

Global site tag (gtag.js) - Google Analytics