案例分析:设计模式与代码的结构特性
请选择一种我们课程中介绍的设计模式,用您熟悉的编程语言提供一个典型的应用范例,并分析其代码结构特性。完成一篇研究报告,具体要求如下:
- 引用关键代码(引用代码是为解释说明服务的,不要贴对解释问题无关的代码)解释该设计模式在该应用场景中的适用性;
- 引入该设计模式后对系统架构和代码结构带来了哪些好处;
- 解释其中用到的多态机制;
- 说明模块抽象封装的方法;
- 分析各个模块的内聚度和模块之间的耦合度;
- 提供该应用范例完整的源代码包括构建部署的操作过程,建议以github版本库URL的方式提供源代码,其中README.md中说明构建部署的操作过程
一.软件工程的设计模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
二.装饰模式
装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下:
Source类是被装饰类,Decorator类是一个装饰类,可以为Source类动态的添加一些功能
2.1 应用场景:
①选扩展一个类能实现的功能,但又不想改变该类的内部代码,同时也不想增加很多子类的情况下扩展类
②希望能够动态而非静态的的为一个对象增加功能,而且还能动态撤销增加的功能,继承虽然可以为对象增加功能
但继承的功能是静态的,不能动态增删。
2.2实现方法概述:
设计一个Component 类充当抽象角色,不应该具体实现,修饰类引用和继承 Component 类,具体扩展类重写父类方法。
2.3 装饰器模式的优缺点
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂
2.2 具体应用范例分析:
假设现在有一家奶茶店现在要卖各种口味的奶茶,如果不使用装饰模式,那么在销售系统中,各种不一样的奶茶都要产生一个类,
如果有5种奶茶类,5种甜品,那么就会产生至少25个类(假设不混合口味),如果使用了装饰模式,我们可以使用一下几个类就能实现,
这也是该设计模式给代码结构带来的好处。
①创建奶茶基类
MilkTea.java
public interface MilkTea {
public String getDescription();
public double getPrice();
}
②创建两个具体的奶茶类,奶茶A,奶茶B
MilkTeaA.java
public class MilkTeaA implements MilkTea { private String description = "奶茶A"; @Override public String getDescription() { return description; } @Override public double getPrice() { return 15; } }
MilkTeaB.java
public class MilkTeaB implements MilkTea { private String description = "奶茶B"; @Override public String getDescription() { return description; } @Override public double getPrice() { return 10; } }
③创建奶茶种类的装饰器
Decorator.java
public class Decorator implements MilkTea { private String description = "我是装饰器,我不知道是哪种奶茶"; @Override public String getDescription() { return description; } @Override public double getPrice() { return 0; //价格由种类来决定 } }
④具体装饰类:给奶茶加入甜品A
DessertA.java
public class DessertA extends Decorator{
private String description = "加了甜品A
!";
private MilkTea milkTea = null;
public DessertA(MilkTea milkTea){
this.milkTea = milkTea;
}
public String getDescription(){
return milkTea.getDescription()+"\n"+description;
}
public double getPrice(){
return milkTea.getPrice()+2; //2表示甜品A
的价格
}
}
⑤具体装饰类:给奶茶加入甜品B
DessertB.java
public class DessertB extends Decorator{
private String description = "加了甜品B
!";
private MilkTea milkTea = null;
public DessertB(MilkTea milkTea){
this.milkTea = milkTea;
}
public String getDescription(){
return milkTea.getDescription()+"\n"+description;
}
public double getPrice(){
return milkTea.getPrice()+4; //4表示甜品B
的价格
}
}
⑥具体装饰类:给奶茶加入甜品C
DessertC.java
public class DessertC extends Decorator{ private String description = "加了
!"; private MilkTea milkTea = null; public DessertC(MilkTea milkTea){ this.milkTea = milkTea; } public String getDescription(){ return milkTea.getDescription()+"\n"+description; } public double getPrice(){ return milkTea.getPrice()+8; //8表示
甜品C
的价格 } }
甜品C
⑦测试
Test.java
public class Test { public static void main(String[] args) { MilkTea milkTea = new MilkTeaA(); //选择了奶茶A milkTea = new DessertA(milkTea); //为
奶茶A
添加甜品A
System.out.println(milkTea.getDescription()+"\n总价格:"+milkTea.getPrice()); } }
milkTea = new DessertB(milkTea); //为
奶茶A
添加甜品B
测试结果:
奶茶A
加入甜品A
加入甜品B
总价格:21.0