黄焖鸡米饭最热卖的外卖之一,国人都喜欢吃,吃过黄焖鸡米饭的应该都知道,除了黄焖鸡米饭主体外,还能够添加各类配菜,如土豆、香菇、鹌鹑蛋、青菜等。若是须要你来设计一套黄焖鸡米饭结帐系统,你该如何设计呢?java
前置条件:主体:黄焖鸡米饭 价格:16,配菜:土豆 价格:二、香菇 价格:二、鹌鹑蛋 价格:二、青菜 价格:1.5git
这还不简单?看个人,你随手就来了下面这段代码。github
public class HuangMenJiMiFan {
// 黄焖鸡价格
private double huangMenJiPrice = 16D;
// 土豆价格
private double potatoPrice = 2D;
// 鹌鹑蛋价格
private double eggPrice = 2D;
// 香菇价格
private double mushroomPrice = 2D;
// 青菜价格
private double vegPrice = 1.5D;
// 总价格
private double totalPrice = 0D;
// 订单描述
private StringBuilder desc = new StringBuilder("黄焖鸡米饭 ");
// 是否加土豆
private boolean hasPotato = false;
// 是否加鹌鹑蛋
private boolean hasEgg = false;
// 是否加香菇
private boolean hasMushroom = false;
// 是否加蔬菜
private boolean hasVeg = false;
public HuangMenJiMiFan(){
this.totalPrice = this.huangMenJiPrice;
}
public void setHasPotato(boolean hasPotato) {
this.hasPotato = hasPotato;
}
public void setHasEgg(boolean hasEgg) {
this.hasEgg = hasEgg;
}
public void setHasMushroom(boolean hasMushroom) {
this.hasMushroom = hasMushroom;
}
public void setHasVeg(boolean hasVeg) {
this.hasVeg = hasVeg;
}
public String getDesc(){
if (hasEgg){
this.desc.append("+ 一份鹌鹑蛋 ");
}
if (hasMushroom){
this.desc.append("+ 一份香菇 ");
}
if (hasPotato){
this.desc.append("+ 一份土豆 ");
}
if (hasVeg){
this.desc.append("+ 一份蔬菜 ");
}
return desc.toString();
}
public double cost(){
if (hasEgg){
this.totalPrice +=this.eggPrice;
}
if (hasMushroom){
this.totalPrice +=this.mushroomPrice;
}
if (hasPotato){
this.totalPrice +=this.potatoPrice;
}
if (hasVeg){
this.totalPrice +=this.vegPrice;
}
return totalPrice;
}
}
复制代码
只要在点黄焖鸡米饭的时候,把添加的配菜设置成true
就好,这段代码确实解决了黄焖鸡米饭结算问题。可是我须要加两份土豆呢?我须要添加一种新配菜呢?或者我新增一个黄焖排骨呢?这时候实现起来就须要去改动原来的代码,这违背了设计模式的开放-关闭原则
设计模式
开放-关闭原则:类应该对扩展开放,对修改关闭微信
上面的设计违背了开放-关闭原则
,为了不这个问题,采用装饰者模式彷佛是一种可行的解决办法。app
装饰者模式:动态的给一个对象添加一些额外的职责,就增长功能来讲,装饰模式比生成子类更为灵活。ide
装饰者模式的通用类图以下: 学习
Component
Decorator
类,而且里面有一个变量指向Component
抽象类装饰者模式的核心概念咱们都知道了,那就来实现一把,用装饰者模式来设计黄焖鸡米饭的结帐系统。测试
Component
类的设计,仔细想一想,无论黄焖鸡米饭仍是配菜都会涉及到金额计算。因此咱们把该方法抽象到Component
类。来设计咱们黄焖鸡米饭结帐系统的Component
类,咱们取名叫作Food
,Food
类的具体设计以下:ui
/** * 核心抽象类 */
public abstract class Food {
String desc = "食物描述";
public String getDesc() {
return this.desc;
}
// 价格计算
public abstract double cost();
}
复制代码
ConcreteComponent
类是咱们具体的被装饰对象,咱们这里的装饰对象是黄焖鸡米饭,咱们来设计咱们黄焖鸡米饭的被装饰对象Rice
类,Rice
类的具体实现以下:
/** * 被装饰者-黄焖鸡米饭 */
public class Rice extends Food{
public Rice(){
this.desc ="黄焖鸡米饭";
}
@Override
public double cost() {
// 黄焖鸡米饭的价格
return 16D;
}
}
复制代码
Decorator
类是装饰者的抽象类,咱们须要定义一个getDesc()
的抽象接口,由于在Food
类中,getDesc()
不是抽象的,在后面的具体装饰者中,须要重写getDesc()
类,因此咱们须要将抽象在装饰者这一层。咱们来设计黄焖鸡米饭结帐系统的装饰者抽象类FoodDecorator
,FoodDecorator
类的具体设计以下:
public abstract class FoodDecorator extends Food {
// 获取描述
public abstract String getDesc();
}
复制代码
ConcreteDecorator
类是具体的装饰者,咱们有四个具体的装饰者,分别是土豆、香菇、鹌鹑蛋、青菜,具体的装饰者须要作的事情是计算出被装饰者装饰完装饰品后的总价格和更新商品的描述。四个具体装饰者的设计以下:
public class Egg extends FoodDecorator {
String desc = "鸡蛋";
// 存放Component对象,该对象多是被装饰后的
Food food;
public Egg(Food food){
this.food = food;
}
// 计算总价 当前Component对象的价格加上当前装饰者的价格
@Override
public double cost() {
return food.cost() + 2D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
复制代码
public class Mushroom extends FoodDecorator {
String desc = "香菇";
Food food;
public Mushroom(Food food){
this.food = food;
}
// 计算总价
@Override
public double cost() {
return food.cost() + 2D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
复制代码
public class Potato extends FoodDecorator {
String desc = "土豆";
Food food;
public Potato(Food food){
this.food = food;
}
// 计算总价
@Override
public double cost() {
return food.cost() + 2D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
复制代码
public class Veg extends FoodDecorator {
String desc = "蔬菜";
Food food;
public Veg(Food food){
this.food = food;
}
// 计算总价
@Override
public double cost() {
return food.cost() + 1.5D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
复制代码
装饰者的全部角色都实现完了,咱们来测试一下使用装饰者模式以后的黄焖鸡结帐系统,编写一个App
测试类。
public class App {
public static void main(String[] args) {
// 点一份米饭
Rice rice = new Rice();
// 加个鸡蛋
Egg egg = new Egg(rice);
// 在加土豆
Potato potato = new Potato(egg);
// 再加一份白菜
Veg veg = new Veg(potato);
System.out.println(veg.getDesc());
System.out.println(veg.cost());
}
}
复制代码
测试结果
使用装饰者模式以后的黄焖鸡米饭结帐系统,在新增配菜或者产品时,咱们不须要修改原先的功能,只须要对类进行扩展就行了,这彻底遵循了开放-关闭原则
。
Component
类无须知道Decorator
类,Decorator
类也不用知道具体的被装饰者。Component
最后多说一句,JDK 中的 java.io
就是用装饰者模式实现的,有兴趣的能够去深刻了解一下。
文章不足之处,望你们多多指点,共同窗习,共同进步
打个小广告,欢迎扫码关注微信公众号:「平头哥的技术博文」,一块儿进步吧。