装饰者模式
一、定义
装饰者模式:动态的给对象添加一些额外的属性或者行为(方法),无需修改原本的对象,直接添加就行,相比于继承,装饰者模式更加的灵活。
UML图:
Component是一个基类,被装饰类ConcreateComponent和装饰类Decorator都是继承这个基类。
二、实例运用
需求:一个人出门,根据不同的时候穿不同的衣服,现有短T,卫衣,夹克。
因为在此需求中,没有基类的抽象类。因此人即代表基类的抽象类Component也代表具体的被装饰者类ConcreteComponent。
第一步:创建被装饰类Person
package com.golf.decoration;
public class Person {
private String name;
public Person(){
}
public Person(String name) {
this.name = name;
}
public void show(){
System.out.println("装扮的是:"+name);
}
}
第二步:创建抽象的装饰类Cloth
package com.golf.decoration;
//装饰类(接口)
public class Cloth extends Person {
private Person component;
//装饰
public void decorate(Person component){
this.component = component;
}
public void show(){ //调用被修饰类Person的show方法
if(component != null)
component.show();
}
}
第三步:创建各个具体的装饰类
Tshirt类
package com.golf.decoration;
//具体的修饰类
public class Tshirt extends Cloth {
@Override
public void show() { //Tshirt类特有的信息
System.out.println("Tshirt");
super.show();
}
}
Jacket类
package com.golf.decoration;
//具体的装饰类
public class Jacket extends Cloth{
@Override
public void show() {
System.out.println("夹克");
super.show();
}
}
Hoodie类
package com.golf.decoration;
//具体的装饰类
public class Hoodie extends Cloth {
@Override
public void show() {
System.out.println("卫衣");
super.show();
}
}
第四步:创建客户端进行调用
package com.golf.decoration;
public class Client {
public static void main(String[] args) {
Person person = new Person("吴彦祖"); //创建被修饰类
// person.show();
Hoodie hoodie = new Hoodie();
Jacket jacket = new Jacket();
hoodie.decorate(person);
jacket.decorate(hoodie);
jacket.show();
}
}
第二个实例:
卖蛋糕,蛋糕原价66元,倘若加奶油需要加10元,倘若加蜡烛加16元
第一步:创建被修饰类和修饰类的基类
package com.golf.decoration2;
//创建被修饰类和修饰类的基类
public abstract class Sweet {
private String name;
//修饰的方法
public String getDescription(){ //让继承的被修饰类的方法能够继承
return name;
}
//修饰的方法
public abstract double cost(); //让继承的被修饰类的方法能够继承
}
第二步:创建被修饰类
package com.golf.decoration2;
//创建被修饰类 concreteComponent
public class Cake extends Sweet {
@Override
public String getDescription() { //写入被修饰类的特性
return "蛋糕";
}
@Override
public double cost() { //写入被修饰类的特性
return 66;
}
}
第二步:创建修饰类的基类
package com.golf.decoration2;
//创建修饰类
public abstract class Decoration extends Sweet{
@Override
public abstract String getDescription(); //创建抽象方法的装饰 便于具体的装饰方法使用
@Override
public abstract double cost();
}
第三步:创建具体的修饰类
package com.golf.decoration2;
//创建修饰类
public class Candle extends Decoration {
private Sweet sweet;
public Candle(Sweet sweet){ //通过构造方法选择修饰那个类
this.sweet = sweet;
}
@Override
public String getDescription() {
return sweet.getDescription()+"蜡烛";
}
@Override
public double cost() {
return sweet.cost()+16;
}
}
package com.golf.decoration2;
//创建修饰类
public class Cream extends Decoration {
private Sweet sweet; //对于修饰类创建基类,以此知道修饰的是哪个类
public Cream(Sweet sweet){
this.sweet = sweet;
}
@Override
public String getDescription() {
return sweet.getDescription()+"奶油";
}
@Override
public double cost() {
return sweet.cost()+10;
}
}
第四步:客户端
package com.golf.decoration2;
public class Client {
public static void main(String[] args) {
Cake cake = new Cake();
String name = cake.getDescription();
double cost = cake.cost();
System.out.print(name);
System.out.println(cost);
Cream cream = new Cream(cake);
Candle candle = new Candle(cream);
Candle candle1 = new Candle(new Cream(new Cake())); //是不是很像IO流中创建时的样子,IO流就是用来装饰者模式
System.out.println(candle1.cost());
System.out.println(cream.getDescription()+cream.cost());
System.out.println(candle.getDescription()+candle.cost());
}
}