设计模式java【装饰者模式】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dtttyc/article/details/79489383

什么是装饰者模式?

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

什么时候用装饰者模式

当新增的装饰者无需独立形成一个类,他的所有功能依附于被装饰无而存在,因为他们使用了组合关系,当你的子类爆炸的时候也可以去实现装饰者模式,不使用继承使用组合模式

装饰者模式与委托进行比较?

装饰者模式可以动态的进行实现,在这个过程使用了组合,一个对象完成之后再为这个对象套一层
委托是相当于委托–》委托介质—》实现者。正因为委托处于在他们之间,所以他们要转换为委托的类型,当然会在进行通信

装饰者模式在哪里体现出动态附加到对象上?

1首先是在main方法中,我们把一个对象当做参数放在一个对象里面,当一个对象完成之后我们对他进行再次的装饰,这也他的核心所在!

Beverage beverage1 = new DarkRoast();
beverag1= new Mocha(beverag1);
beverag1=new Whip(beverage1)

为什么组合比继承更好?

组合适应了系统的变化,并且适应从静态到动态的去变化,最开始的时候们可能会感觉继承非常好,原因是因为门体会到了复用的好处,但是如果深入学习会发现继承破坏了封装性!这些就导致子类的父类的不一样,也无法预知,并且继承也不能实现动态功能

代码体现组合?

最初的时候我们组合这条线是与下面进行关联的,可是突然在写代码的时候发现不对,因为这个时候我发现如果我想让另一个方法也要组合,那我其他是还要在画一条线,所以发现错误之后我就更正过来了,也知道为什么是这样了
这里写图片描述


这是更改之后的我们他们的父类进行关联
这里写图片描述

Beverage beverage
public mocha (Beverage beverage){
  this.bevergae=beverage;
}

为什么使用构造方法?

如果我们用了构造函数,那么在我们程序运行的时候,我们直接对我们对我们的程序进行赋值,所以我们跟本不用管,这个对象里面是否有值,我们是否指明了对象,一旦你调用了他的方法那么他就会走构造函数,然后他就会被存储起来,这个时候他基于这个对象来再次的封装


在进行装饰模式之前我们应该干些什么?

在他之前时候的时候我们会发现我们使用继承来达到的我们的功能,例如,现在有一个X功能,但是你老板又给你突然添加了两个格外的功能,这个时候你就可以使用继承来满足你的条件,让B类和C类同时继承与A类,这样子类就可以A类的方法并且还可以让B类和C类拥有各自特性的方法!


但是你会发现BC类我们都可以写上去,但是如果你的老板给扩展了100000个功能,难道你还要写100000个类吗!?所以这个时候我们就是用了装饰者模式,动态的去扩充就可以了

有了装饰者模式之后是什么样子的?

加入你有一个A类需要扩充X功能,这个时候我们正需要定义一个B类,让B类去实习这个X的功能,创建B类的时候,再让A类的对象传入到B对象中,让B对象完成之后使用A的对象,这个过程都是动态去实现的!


使用继承的时候是编译时静态决定的,而使用组合的方法扩展对象行为动态运行的时候进行扩展


缺点

当装饰层次过多的时候,这个时候哦系统的复杂性就会提高,所以一般要求装饰在3层之内,否则就不要使用装饰者模式了

抽象方法应该怎么写?

书写格式
1。访问修饰符
2。抽象关键字
3。是什么类型的
4。名字是什么

这是抽象类
public abstract class XX{
}
//这是抽象方法
public abstract String XX();

什么是委托?

委托是一个类他定义了方法的类型,使得可以将一个方法当做另一个方法的参数来进行传递,当方法动态的赋给参数的做法我们在写程序中可以省去大量的If else 语句,提高系统的扩展性
一旦委托分配了方法,委托将于该方法具有相同的行为,委托与其他方法一样都具有参数返回值
委托的全英是delegate
使用委托的场景就相当于是,发送者—–》委托——-》接受者,委托在中间起到一个介质的关系
如果不使用委托,那么我可能使用大量的switch 语句,并且我们没有面向OOP的原则,为什么呢?是因为我不能更好的去扩展我们的程序
例如代码


不使用委托?

public void EnglishSpeaker(string name)
{
XX
}
public void ChineseSpeaker(string name)
{
XX
}
客户端进行调用
switch (lang)
{
case Language.Chinese:
XX
break;
case Language.English:
XX、
break;
default :
break;
}

这个时候你可能感觉还没有问题,但是如果这个时候告诉你让你加一个日语再加一个西拔牙语言,那么你就需要些多个case,所以代码的扩展性非常的差!所以这个时候我们可以使用委托来进行改变他!

使用委托?

1.这个表示的 public delegate void SayHello(string othername);
定义函数用于得到委托(类型)接受者,和委托的对象名字
SayHello表示我们的最初定义的委托类型,而othername使我们希望实现的时候给我显示出来的数据
当我们代码调到hello的时候,这个时候程序调到关于delegate委托类型,然后我们可以委托类型他就会自动执行委托,然后自动的调到hello参数所传过来的参数
这就是为什么我们要把类型转换为委托类型的,因为如果不转换为委托类型的,那么下一步我们没有办法调到我们的delegate,那么delegate委托就无法帮助我们找到我们的实现的对象啦~

public void hello(SayHello hello, String othername) {
      hello(othername);
  }

3在main方法的时候我们需要把我们的最开始的对象转化为委托类型的
然后调用我们的要执行的方法,传进去我们的对象和name

为什么我们要在CondimentDecorator中使用抽象方法getdescription?

我们不只是简单描述饮料,我们哟啊把完整的套料也要描述出来,所以这个时候我们在父类抽象出来一个getdescription,然后我们进行重写,加上饮料和材料都描述出来!


在我们做咖啡的时候我们应该如何设计我们的思路?

1首先我们应该有一个抽象类,里面使我们要实现的需求,例如,描述,钱,这些东西
2还有一个抽象类是关于我们后面对于材料的描述抽象方法
3我们需要做咖啡的时候我底料的方法,用于继承我们的第一个抽象类
4我们需要装饰者也就是我们的材料。
5在我们底料方法里面都有构造函数,他们的作用就是在加载类的时候我们直接告诉大家我叫什么名字,在材料方法中也有构造函数是为了记录我们的饮料
6在mian方法中我们利用多态调用我们的方法,然后把对象当做参数传到方法里面。


总结

通过这次学习让我深刻体会到了设计思想,以及这个东西为什么会出现???

没有更多推荐了,返回首页