这篇博客是我学习装饰者模式的时候产生的误区,装饰者模式是遵循开放关闭原则,策略模式是多组合少继承原则。准确来说应该是从本质上误会了装饰者模式,装饰者模式应该是你给我个鸡蛋面就行了我不会去加鸡蛋加面,你给我把那些鸡蛋面,牛肉面封装好我直接调用就行了而不是我自己去放。如果还不能理解的可以想想java的io流那里就是装饰者模式,你们用的都是封装好的流对象而不是让你去怎么样放变成那个流对象。所以我会重新再写一篇装饰者模式。但是由于这篇博客还是比较好的代码比较有弹性就不删了,只是在最开始就没弄清楚装饰者模式我们需要给别人提供什么。留给后面的人看看吧。
我也不确定这是装饰者模式吗?但是我实现了和装饰者模式一样的结果。因为之前看了策略模式了解到我们在代码的编辑中,应该少用继承,多用组合。所以这个应该算是用组合写出来的实现了装饰者模式的效果。并且我目前认为这个比装饰者模式还要好,更灵活。
个人见解:
策略模式要做到的效果是,我们需要从很多鸭子中找到我们需要的那一个鸭子。
装饰者模式要做到的效果是,我们要把不一样的东西自由组合起来,就像热干面可以就是热干面,热干面可以加鸡蛋或者别的很多东西。
虽然他们两个不一样,但是还是可以把设计模式中的很多地方一起公用的。
策略模式:多组合,少继承
装饰者模式:开放关闭原则,不是所有的地方都要装饰者模式,只是在日后代码可能会被修改的地方使用装饰者模式。
定义一个noodle面条接口
public interface Noodle {
public String getNoodleName();
public Double getNoodlePrice();
}
两个实现类分别是热干面和泡面
public class HotDryNoodle implements Noodle{
@Override
public String getNoodleName() {
return "热干面";
}
@Override
public Double getNoodlePrice() {
return 4.0;
}
}
public class FoamSurface implements Noodle{
@Override
public String getNoodleName() {
return "泡面";
}
@Override
public Double getNoodlePrice() {
return 5.0;
}
}
定义一个面条装饰物的接口,并且实现它的两个实现类,鸡蛋和牛肉
public interface NoodleDecorator {
public String getNoodleDecoratorName();
public Double getNoodleDecoratorPrice();
}
public class Egg implements NoodleDecorator{
@Override
public String getNoodleDecoratorName() {
return "鸡蛋";
}
@Override
public Double getNoodleDecoratorPrice() {
return 2.0;
}
}
public class Beef implements NoodleDecorator{
@Override
public String getNoodleDecoratorName() {
return "牛肉";
}
@Override
public Double getNoodleDecoratorPrice() {
return 5.0;
}
}
武汉最常见的就是蔡林记了,于是我们写一个蔡林记的类卖面
public class CaiLinJi {
//不管是鸡蛋的还是牛肉的必须有一碗面
private Noodle noodle;
//定义最后这碗面的价格
private Double price = 0.0;
//可以有很多装饰品,鸡蛋,牛肉等,因为客户可以选择不要那些,所以用一个不定参来接受最后转换到这个集合里放着
private List noodleDecorators = new ArrayList();
//我们只给出有参的构造方法。让那些只看不买的人没得聊。
public CaiLinJi(Noodle noodle, NoodleDecorator... noodleDecorator) {
this.noodle = noodle;
for (int i = 0; i < noodleDecorator.length; i++) {
noodleDecorators.add(noodleDecorator[i]);
}
}
public Double getPrice() {
price = price + noodle.getNoodlePrice();
for (NoodleDecorator noodleDecorator : noodleDecorators) {
price = price + noodleDecorator.getNoodleDecoratorPrice();
}
return price;
}
public StringBuffer getNoodleName() {
StringBuffer noodleName = new StringBuffer();
noodleName.append("您点的面是:"+noodle.getNoodleName());
for (NoodleDecorator noodleDecorator : noodleDecorators) {
noodleName.append("加上"+noodleDecorator.getNoodleDecoratorName());
}
return noodleName;
}
public Noodle getNoodle() {
return noodle;
}
public void setNoodle(Noodle noodle) {
this.noodle = noodle;
}
public List getNoodleDecorators() {
return noodleDecorators;
}
public void setNoodleDecorators(List noodleDecorators) {
this.noodleDecorators = noodleDecorators;
}
}
最后就是测试方法了。
public class TestMain {
public static void main(String[] args) {
CaiLinJi caiLinJi = new CaiLinJi(new FoamSurface(),new Egg());
System.out.println(caiLinJi.getPrice());
System.out.println(caiLinJi.getNoodleName());
}
}
成功输出
7.0
您点的面是:泡面加上鸡蛋
所以我们需要做的就是写一个豆腐的类并且实现面条装饰物的接口
public class Doufu implements NoodleDecorator{
@Override
public String getNoodleDecoratorName() {
return "豆腐";
}
@Override
public Double getNoodleDecoratorPrice() {
return 1.5;
}
}
完事,我们可以在测试一下。
public class TestMain {
public static void main(String[] args) {
CaiLinJi caiLinJi = new CaiLinJi(new FoamSurface(),new Doufu());
System.out.println(caiLinJi.getPrice());
System.out.println(caiLinJi.getNoodleName());
}
}
此时输入
6.5
您点的面是:泡面加上豆腐
希望对此有不同看法的大佬们可以交流交流共同学习。