装饰模式——Decorator
文章目录
案例展示——Decorator怎么用?
现在有这样一种场景:关于二手车我们都不会陌生,或多或少我们都会有接触。那你有没有想过,如何才能把一辆二手车卖出好的价钱呢?是直接和买主摊牌二手车的所有性能参数,还是会适当的加以修饰一下来获得一个好的价位呢?诚然,所谓商场之道,诚信至上,我们当然需要诚实的与买主说清楚二手车的各种参数,但是在商言商,我想些许修饰也是不过分的,下面是一家二手车4S店卖二手车的一个类图设计:
类图元素分析:
-
SHCar:二手车抽象类,里面有两个基本的方法,show()方法用于向用户展示二手车的基本参数;order()方法为用户下订单。
-
SHBaomaCar:具体的二手车类型
-
Decorator:一个抽象的装饰类,它会对每辆二手车进行装饰
-
PowerEngineDecorator:具体的装饰类,继承了Decorator,用于装饰二手车的引擎
-
FastSpeedDecorator:具体的装饰类,继承了Decorator,用于装饰二手车的速度
下面是具体的代码展示:
// 抽象车类
public abstract class SHCar {
// 给客户展示二手车的基本信息
public abstract void show();
// 用户下订单
public abstract void order(String name);
}
// 具体的类型
public class SHBaomaCar extends SHCar{
// 展示一下二手宝马车
public void show() {
System.out.println("型号:宝马X6");
System.out.println("颜色:宝石蓝");
System.out.println("发动机:动力好");
System.out.println("推荐:性价比高,值得拥有");
}
// 用户下订单
public void order(String name) {
System.out.println("我是 " + name + ",这辆车我要了!");
}
}
// 抽象装饰器
public abstract class Decorator extends SHCar{
// 那种类型的二手车:宝马,奔驰,奥迪,法拉利....
private SHCar sc;
// 构造函数,传入二手车
public Decorator(SHCar sc) {
this.sc = sc;
}
// 查看二手车的具体信息
public void show() {
this.sc.show();
}
// 用户下订单
public void order(String name) {
this.sc.order(name);
}
}
// 引擎装饰器
public class PowerEngineDecorator extends Decorator{
// 构造函数
public PowerEngineDecorator(SHCar sc) {
super(sc);
}
// 说说这辆车的强大的引擎
private void showEngine() {
System.out.println("====进口引擎,动力杆杆的!!!====");
}
// 在向用户展示之前先给他说一下
@Override
public void show() {
this.showEngine();
super.show();
}
}
// 速度装饰器
public class FastSpeedDecorator extends Decorator {
// 构造函数
public FastSpeedDecorator(SHCar sc) {
super(sc);
}
// 说说这辆车的速度:百米加速3秒!
private void showSpeed() {
System.out.println("=====百米加速3秒!!!=====");
}
// 在展示之后和用户说一下,增加吸引力
@Override
public void show() {
super.show();
this.showSpeed();
}
}
// 客户买车
public class Client {
public static void main(String[] args) {
// 没有修饰的原装车
SHCar sc = new SHBaomaCar();
// 修饰一下:强大的引擎
sc = new PowerEngineDecorator(sc);
// 强调一下:超快的速度
sc = new FastSpeedDecorator(sc);
// 展示
sc.show();
// 用户很开心,下单!
sc.order("张三");
}
}
// 运行结果如下:
====进口引擎,动力杆杆的!!!====
型号:宝马X6
颜色:宝石蓝
发动机:动力好
推荐:性价比高,值得拥有
=====百米加速3秒!!!=====
我是 张三,这辆车我要了!
上面的例子中使用的就是装饰模式,通过一个抽象的装饰器得到它要装饰的类型,然后交给具体的装饰类型去装饰,这样在没有改变二手车基本参数的情况下,使其给客户的观感更好,人家自然很高兴就下单了。
深入分析——Decorator是什么?
Decorator的定义
定义: 动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。下面是装饰模式的通用类图:
-
Conponent组建:一个接口或者抽象类,定义最核心的对象,如二手车
-
ConcreateComponent组建:具体的构建,被装饰的对象
-
Decorator组建:装饰者
-
ConcreateDecorator:具体的装饰者
下面是具体代码
// 抽象构建
public abstract class Component {
// 抽象方法
public abstract void operate();
}
// 具体构建
public class ConcreateComponent extends Component {
// 具体实现
public void operate() {
// 业务逻辑
}
}
// 抽象装饰器
public abstract class Decorator extends Component{
// 修饰哪个组建
private Component component = null;
// 通过构造函数传递被修饰者
public Decorator(Component component) {
this.component = component;
}
// 委托给被修饰者执行
@Override
public void operate() {
this.component.operate();
}
}
// 具体的装饰器
public class ConcreateDecorator1 extends Decorator {
// 传递被修饰者
public ConcreateDecorator1(Component component) {
super(component);
}
// 定义自己的修饰方法
private void method1() {
// 修饰
}
// 重写父类的operate()方法
public void operate() {
this.method1();
super.operate();
}
}
// 具体的装饰器
public class ConcreateDecorator2 extends Decorator {
// 传递被修饰者
public ConcreateDecorator2(Component component) {
super(component);
}
// 定义自己的修饰方法
private void method2() {
// 修饰
}
// 重写父类的operate()方法
public void operate() {
super.operate();
this.method2();
}
}
// 场景类
public class Client {
public static void main(String[] args) {
Component component = new ConcreateComponent();
// 第一次修饰
component = new ConcreateDecorator1(component);
// 第二次修饰
component = new ConcreateDecorator2(component);
// 运行
component.operate();
}
}
Decorator的优点
-
装饰类和被装饰类可以独立发展,而不会相互耦合
-
装饰模式是继承关系的一个替代方案
-
装饰模式可以动态的扩展一个实现类的功能
Decorator的缺点
-
装饰类太多会增加复杂性
-
会产生很多小对象,增加系统的复杂性
-
虽然比继承更加灵活,当时也意味着比继承更加容易出错。在出现错误后,由于多层装饰,排错很困难,需要逐级排查,较为繁琐
Decorator的应用场景
-
需要扩张一个类的功能或给一个类增加附加功能
-
需要动态的给一个对象增加功能,这些功能可以再动态的撤销
-
需要为一批兄弟类改装或加装功能
参考
《设计模式之禅》