装饰器设计模式
设计模式 :为了达到目的,设计组织代码的一种固定的模式。
装饰器设计模式,本质上是用装饰器对某个类的对象的某个属性进行装饰,也就是说装饰器和被装饰的对象都具有相同的属性,那么在这个设计模式中,我们就可以把这些相同的属性抽象成一个接口,由装饰器和被装饰的对象共同实现,为了能在装饰器类中对被装饰的某个类的属性进行修饰,所以装饰器需要一个有参构造器来传递被装饰的类的对象实现多态,然后在装饰器的类中对传递过来的 被装饰的对象进行修饰。
下面是使用装饰器设计模式的简单程序实例:
package com.company;
/**
* 集装箱设计模式
*
* @author 发达的范
* @version 1.0
* @date 2021/04/03 16:52
*/
public class Decorate01 {
public static void main(String[] args) {
Person p = new Person();
p.say();
Amplifier am = new Amplifier(p);
am.say();
}
}
interface Say {//接口中只能有抽象方法和属性
void say();
}
class Person implements Say {
private int high = 180;
@Override//实现接口,必须要实现/重写接口的所有方法,这一点与继承不同
public void say() {
System.out.println("人的身高" + this.high);//最好用this访问类的属性,因为多态
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
}
class Amplifier implements Say {
private Person person;
public Amplifier(Person person) {
this.person = person;
}
@Override
public void say() {
System.out.println("人的身高" + person.getHigh() * 100);
}
}
这个程序综合性很强,刚好是对以前接口及其实现,构造器,类之间的关系等知识点的复习。
装饰器设计模式,本质上是用装饰器对某个类的对象的某个属性进行装饰,也就是说装饰器和被装饰的对象都具有相同的属性,那么在这个设计模式中,我们就可以把这些相同的属性抽象成一个接口,由装饰器和被装饰的对象共同实现,为了能在装饰器类中对被装饰的某个类的属性进行修饰,所以装饰器需要一个有参构造器来传递被装饰的类的对象实现多态,然后在装饰器的类中对传递过来的 被装饰的对象进行修饰。
简而言之:
- 装饰器用来装饰被修饰的类的对象的什么方法,那么就把这个方法抽象成一个接口,由装饰器类和被装饰的类共同实现;
- 在装饰器类中写入被装饰的类的对象的属性,并使用有参构造器进行构造,以便传递对象进行修饰。
Person类和Amplifier类都实现了Say接口,而Amplifier类里面有一个Person类的对象(目的就是为了对Person的对象进行装饰),在Amplifier类里面,使用与Person类相同的方法(实现接口的方法)进行装饰,本质上就是在Amplifier类中用相同的方法名把Person类的对象的方法加点东西修饰一下。
简单的设计模式有:单例,工厂,代理等。
下面是一个装饰器设计模式的完整实例:
package com.company;
/**
* 装饰器设计模式
* 模拟咖啡制作
* <p>
* 1.抽象组件:需要装饰的抽象对象(接口/抽象父类)
* 2.具体组件:要装饰的对象
* 3.抽象装饰类:包含了对抽象组件的引用以及装饰类共有的方法
* 4.具体装饰类:借助抽象装饰类来修饰具体组件(被装饰的对象)
*
* @author 发达的范
* @version 1.0
* @date 2021/04/03 17:32
*/
public class Decorate02 {
public static void main(String[] args) {
Drink coffee = new Coffee();//这里均使用的父类的引用指向子类,但是字节使用子类进行实例化也会是可以的
Drink milk = new Milk(coffee);
System.out.println(milk.info() + milk.cost());
Drink sugar = new Sugar(coffee);
System.out.println(sugar.info() + sugar.cost());
sugar = new Sugar(milk);
System.out.println(sugar.info() + sugar.cost());
}
}
//1.抽象组件,被装饰的对象和装饰器共有的属性,装饰器就是来修饰这些属性
interface Drink {
double cost();
String info();
}
//2.具体组件,被装饰的对象及其属性
class Coffee implements Drink {//具体被装饰的类Coffee
private String name = "原味咖啡";
private int price=10;
@Override
public double cost() {
return price;
}
@Override
public String info() {
return name;
}
}
//3.抽象装饰类,上一个程序里面没有使用抽象装饰类,是直接在具体装饰类里面进行修饰的
//这里使用抽象装饰类进行被装饰的对象的传递,传递给具体装饰类
abstract class Decorate implements Drink {
//对抽象组件的引用
private Drink drink;
public Decorate(Drink drink) {
this.drink = drink;
}
@Override
public double cost() {
return this.drink.cost();
}
@Override
public String info() {
return this.drink.info();
}
}
//4.具体的装饰类,具体装饰类是抽象装饰类的子类(拥有父类所有的属性和方法),借用抽象装饰类的有参构造器来出传递被装饰的对象
//在具体装饰类中使用super关键字调用抽象装饰类中的属性和方法(是被装饰对象的),得到返回值,然后在具体装饰类中修饰
class Milk extends Decorate {
public Milk(Drink drink) {
super(drink);
}
@Override
public double cost() {
return super.cost() * 4;
}
@Override
public String info() {
return super.info() + "加入了牛奶";
}
}
class Sugar extends Decorate {
public Sugar(Drink drink) {
super(drink);
}
@Override
public double cost() {
return super.cost() * 5;
}
@Override
public String info() {
return super.info() + "加入了糖";
}
}
运行结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RXTDLGKJ-1620736155988)(E:(A)]PostgraduateFlies\JavaLearning\TyporaFiles\第二阶段\17Java装饰器设计模式.assets\image-20210403223552949.png)
装饰器设计模式,四步走:
- 1.抽象组件:需要装饰的抽象对象(接口/抽象父类)
- 2.具体组件:要装饰的对象
- 3.抽象装饰类:包含了对抽象组件的引用以及装饰类共有的方法
- 4.具体装饰类:被装饰的对象
简而言之就是,2具体组件,3抽象装饰类和4具体装饰类都必须含有1抽象组件,重写1抽象组件的所有方法,具体装饰类是继承抽象装饰类并借助抽象装饰类来访问修饰具体的组件。