当前位置 : 主页 > 网络编程 > net编程 >

Java设计模式:装饰者模式(Decorator Pattern)

来源:互联网 收集:自由互联 发布时间:2023-09-06
装饰者模式,涉及的重要设计原则:类应该对扩展开放,对修改关闭。 装饰者模式定义: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代


装饰者模式,涉及的重要设计原则:类应该对扩展开放,对修改关闭。

装饰者模式定义:

装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

UML类图:

Java设计模式:装饰者模式(Decorator Pattern)_Decorator Pattern

装饰者模式事例:

咖啡店

咖啡种类:

1)深焙咖啡(DarkRoast)

2)家庭混合咖啡(HouseBlend)

3)浓咖啡(Espresso)

4)低咖啡因咖啡(Decaf)

5)其它咖啡。。。

咖啡调料:

1)摩卡(Mocha)

2)牛奶(Milk)

3)豆浆(Soy)

4)奶泡(Whip)

5)其它调料。。。

点单:

要一份加了摩卡和奶泡的深焙咖啡...等等

UML类图

Java设计模式:装饰者模式(Decorator Pattern)_java_02

代码实现:

Beverage.java

package com.jing.decorator;

/**
* 所有饮料的抽象超类
* @author LiuJing
*
*/
public abstract class Beverage {

/**
* 饮料的名字
*/
String description = "Unknow Beverage";

/*
* 获取饮料的名字
*/
public String getDescription(){
return description;
}


/***
* 获取饮料的价格
* @return 返回计算后的总价
*/
public abstract double cost();

}

DarkRoast.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 深烤咖啡
* @author LiuJing
*
*/
public class DarkRoast extends Beverage {

/***
* 构造时确定名字
*/
public DarkRoast(){
description = "DarkRoast";
}

/***
* 价格
*/
public double cost() {
double cost = 10.0;

// 用于保存2位小数
DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}
}

Decaf.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 低咖啡因咖啡
* @author LiuJing
*
*/
public class Decaf extends Beverage {

/***
* 构造时确定名字
*/
public Decaf() {
description = "Decaf";
}

/***
* 价格
*/
public double cost() {
double cost = 11.0;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}
}

Espresso.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 浓咖啡
* @author LiuJing
*
*/
public class Espresso extends Beverage {

/***
* 构造时确定其名字
*/
public Espresso(){
description = "Espresso";
}

/***
* 方法返回 该饮料的价格
*/
public double cost() {
double cost = 12.0;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}
}

HouseBlend.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 家庭混合咖啡
* @author LiuJing
*
*/
public class HouseBlend extends Beverage {

/***
* 构造时确定其名字
*/
public HouseBlend(){
description = "HouseBlend";
}

/***
* 返回该咖啡的价格
*/
public double cost() {
double cost = 13.0;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

CondimentDecorator.java

package com.jing.decorator;

/***
* 调料装饰者抽象超类,继承至 Beverage,便于类型的统一,能彼此替换。
* @author LiuJing
*
*/
public abstract class CondimentDecorator extends Beverage {

/***
* 用于保存要装饰的咖啡对象
*/
Beverage beverage;

/***
* 所有子类都必须重新实现 getDescription()方法
*/
public abstract String getDescription();

}

Milk.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 咖啡调料 牛奶 Milk >> CondimentDecorator >> Beverage
* @author LiuJing
*
*/
public class Milk extends CondimentDecorator {


/**
* 构造时确定要加给谁
* @param beverage
*/
public Milk(Beverage beverage){
this.beverage = beverage;
}


/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Milk";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
cost += 0.1;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}


Mocha.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 咖啡调料 摩卡 Mocha >> CondimentDecorator >> Beverage
*
* @author LiuJing
*
*/
public class Mocha extends CondimentDecorator {


/**
* 构造时确定要加给谁
*
* @param beverage
*/
public Mocha(Beverage beverage) {
this.beverage = beverage;
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Mocha";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
cost += 0.1;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Soy.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 咖啡调料 豆浆 Soy >> CondimentDecorator >> Beverage
*
* @author LiuJing
*
*/
public class Soy extends CondimentDecorator {


/**
* 构造时确定要加给谁
*
* @param beverage
*/
public Soy(Beverage beverage) {
this.beverage = beverage;
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Soy";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
cost += 0.1;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Whip.java

package com.jing.decorator;

import java.text.DecimalFormat;

/***
* 咖啡调料 奶泡 Whip >> CondimentDecorator >> Beverage
*
* @author LiuJing
*
*/
public class Whip extends CondimentDecorator {


/**
* 构造时确定要加给谁
*
* @param beverage
*/
public Whip(Beverage beverage) {
this.beverage = beverage;
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Whip";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
cost += 0.1;

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

测试类

Test.java

package com.jing.decorator;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub


// 点了一份浓咖啡
Beverage beverage = new Espresso();
System.out.println(
beverage.getDescription() + ": $ " + beverage.cost());

// 点了一份深烤
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2); // 加 摩卡装饰
beverage2 = new Mocha(beverage2); // 再加 摩卡装饰
beverage2 = new Whip(beverage2); // 再加 奶泡装饰
System.out.println(
beverage2.getDescription() + ": $ " + beverage2.cost());

// 点了一份家庭混合
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3); // 加 豆浆装饰
beverage3 = new Mocha(beverage3); // 再加 摩卡装饰
beverage3 = new Whip(beverage3); // 再加 奶泡装饰
System.out.println(
beverage3.getDescription() + ": $ " + beverage3.cost());

// 用 工厂模式 和 生成器模式,可以更好的建立被 装饰者对象
}

}

输出:

Espresso: $ 12.0
DarkRoast, Mocha, Mocha, Whip: $ 10.3
HouseBlend, Soy, Mocha, Whip: $ 13.3


扩展:

现在咖啡要有区分 大,中,小杯的价格;

同理,

调料因为杯的大小也要区分不同的价格;

Beverage.java

package com.jing.decorator.size;

/**
* 所有饮料的抽象超类
* @author LiuJing
*
*/
public abstract class Beverage {

/**
* 杯子的容量类型
*/
public final static int TALL = 1;
public final static int GRANDE = 2;
public final static int VENTI = 3;

/**
* 杯子的容量
*/
private int volume = 2; // 默认为中杯

public int getSize() {
return volume;
}

public void setSize(int valume) {
this.volume = valume;
}

public String getSizeDescription() {

String type = "未知杯的大小 ";
switch(volume){
case TALL:
type = "小杯";
break;
case GRANDE:
type = "中杯";
break;
case VENTI:
type = "大杯";
break;
}

return type;
}

/**
* 饮料的名字
*/
String description = "Unknow Beverage";



/*
* 获取饮料的名字
*/
public String getDescription(){
return description;
}


/***
* 获取饮料的价格
* @return 返回计算后的总价
*/
public abstract double cost();

}


DarkRoast.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 深烤咖啡
* @author LiuJing
*
*/
public class DarkRoast extends Beverage {

/***
* 构造时确定名字
*/
public DarkRoast(){
description = "DarkRoast";
}

public DarkRoast(int volume){
setSize(volume);
description = "DarkRoast";
}

/***
* 价格
*/
public double cost() {
double cost = 0.0;
if (getSize() == Beverage.TALL) {
cost = 10.0;
}else if (getSize() == Beverage.GRANDE){
cost = 15.0;
}else if (getSize() == Beverage.VENTI){
cost = 20.0;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Decaf.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 低咖啡因咖啡
* @author LiuJing
*
*/
public class Decaf extends Beverage {

/***
* 构造时确定名字
*/
public Decaf() {
description = "Decaf";
}
public Decaf(int volume){
setSize(volume);
description = "Decaf";
}

/***
* 价格
*/
public double cost() {
double cost = 0.0;
if (getSize() == Beverage.TALL) {
cost = 11.0;
}else if (getSize() == Beverage.GRANDE){
cost = 16.0;
}else if (getSize() == Beverage.VENTI){
cost = 21.0;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Espresso.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 浓咖啡
* @author LiuJing
*
*/
public class Espresso extends Beverage {

/***
* 构造时确定其名字
*/
public Espresso(){
description = "Espresso";
}

public Espresso(int volume){
setSize(volume);
description = "Espresso";
}

/***
* 方法返回 该饮料的价格
*/
public double cost() {
double cost = 0.0;
if (getSize() == Beverage.TALL) {
cost = 12.0;
}else if (getSize() == Beverage.GRANDE){
cost = 17.0;
}else if (getSize() == Beverage.VENTI){
cost = 22.0;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}
}


HouseBlend.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 家庭混合咖啡
* @author LiuJing
*
*/
public class HouseBlend extends Beverage {

/***
* 构造时确定其名字
*/
public HouseBlend(){
description = "HouseBlend";
}

public HouseBlend(int volume){
setSize(volume);
description = "HouseBlend";
}

/***
* 返回该咖啡的价格
*/
public double cost() {
double cost = 0.0;
if (getSize() == Beverage.TALL) {
cost = 13.0;
}else if (getSize() == Beverage.GRANDE){
cost = 18.0;
}else if (getSize() == Beverage.VENTI){
cost = 23.0;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}


CondimentDecorator.java

package com.jing.decorator.size;

/***
* 调料装饰者抽象超类,继承至 Beverage,便于类型的统一,能彼此替换。
* @author LiuJing
*
*/
public abstract class CondimentDecorator extends Beverage {

/***
* 要装饰的咖啡对象
*/
Beverage beverage;


/***
* 所有子类都必须重新实现 getDescription()方法
*/
public abstract String getDescription();

}


Milk.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 咖啡调料 牛奶 Milk >> CondimentDecorator >> Beverage
* @author LiuJing
*
*/
public class Milk extends CondimentDecorator {


/**
* 构造时确定要加给谁
* @param beverage
*/
public Milk(Beverage beverage){
this.beverage = beverage;
setSize(beverage.getSize());
}

public int getSize(){
return beverage.getSize();
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Milk";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
if (getSize() == Beverage.TALL){
cost += 0.1;
} else if (getSize() == Beverage.GRANDE){
cost += 0.2;
} else if (getSize() == Beverage.VENTI){
cost += 0.3;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Mocha.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 咖啡调料 摩卡 Mocha >> CondimentDecorator >> Beverage
* @author LiuJing
*
*/
public class Mocha extends CondimentDecorator {


/**
* 构造时确定要加给谁
* @param beverage
*/
public Mocha(Beverage beverage){
this.beverage = beverage;
setSize(beverage.getSize());
}

public int getSize(){
return beverage.getSize();
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Mocha";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
if (getSize() == Beverage.TALL){
cost += 0.1;
} else if (getSize() == Beverage.GRANDE){
cost += 0.2;
} else if (getSize() == Beverage.VENTI){
cost += 0.3;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}


Soy.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 咖啡调料 豆浆 Soy >> CondimentDecorator >> Beverage
* @author LiuJing
*
*/
public class Soy extends CondimentDecorator {


/**
* 构造时确定要加给谁
* @param beverage
*/
public Soy(Beverage beverage){
this.beverage = beverage;
setSize(beverage.getSize());
}

public int getSize(){
return beverage.getSize();
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Soy";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
if (getSize() == Beverage.TALL){
cost += 0.1;
} else if (getSize() == Beverage.GRANDE){
cost += 0.2;
} else if (getSize() == Beverage.VENTI){
cost += 0.3;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Whip.java

package com.jing.decorator.size;

import java.text.DecimalFormat;

/***
* 咖啡调料 奶泡 Whip >> CondimentDecorator >> Beverage
* @author LiuJing
*
*/
public class Whip extends CondimentDecorator {


/**
* 构造时确定要加给谁
* @param beverage
*/
public Whip(Beverage beverage){
this.beverage = beverage;
setSize(beverage.getSize());
}

public int getSize(){
return beverage.getSize();
}

/***
* 不仅显示当前名,还说明被装饰的名字
*/
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + ", Whip";
}

/***
* 获取本身的价格和咖啡的价格
*/
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
if (getSize() == Beverage.TALL){
cost += 0.1;
} else if (getSize() == Beverage.GRANDE){
cost += 0.2;
} else if (getSize() == Beverage.VENTI){
cost += 0.3;
}

DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(cost));
}

}

Test.java

package com.jing.decorator.size;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub


// 点了一份浓咖啡
Beverage beverage = new Espresso(); // 使用默认中杯
System.out.println(beverage.getSizeDescription()
+ beverage.getDescription() + ": $ " + beverage.cost());

// 点了一份深烤
Beverage beverage2 = new DarkRoast();// 默认为中号
beverage2.setSize(Beverage.TALL); // 重新设置杯号为小号
beverage2 = new Mocha(beverage2); // 加 摩卡装饰
beverage2 = new Mocha(beverage2); // 再加 摩卡装饰
beverage2 = new Whip(beverage2); // 再加 奶泡装饰
System.out.println(beverage2.getSizeDescription()
+ beverage2.getDescription() + ": $ " + beverage2.cost());

// 点了一份家庭混合
Beverage beverage3 = new HouseBlend(Beverage.VENTI); // 构造初始时就设为大号
beverage3 = new Soy(beverage3); // 加 豆浆装饰
beverage3 = new Mocha(beverage3); // 再加 摩卡装饰
beverage3 = new Whip(beverage3); // 再加 奶泡装饰
System.out.println(beverage3.getSizeDescription()
+ beverage3.getDescription()
+ ": $ " + beverage3.cost());

// 用 工厂模式 和 生成器模式,可以更好的建立被 装饰者对象
}

}


输出:

中杯Espresso: $ 17.0
小杯DarkRoast, Mocha, Mocha, Whip: $ 10.3
大杯HouseBlend, Soy, Mocha, Whip: $ 23.9


【转自:大丰网站建设 http://www.1234xp.com/dafeng.html 欢迎留下您的宝贵建议】
上一篇:Go语言如何自定义linter(静态检查工具)
下一篇:没有了
网友评论