设计模式——装饰模式

装饰模式

装饰模式:动态地给一个对象添加一些额外的职责。 就增加功能来说,装饰模式相比生成子类更为灵活。

在类图中,有四个角色需要说明:

  • Component抽象构件:Component是一个接口或者是抽象类,就是定义最核心的对象,也就是最原始的对象。注意:在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。
  • ConcreteComponent具体构件:ConcreteComponent是最核心接口或抽象类的实现,要装饰的就是它。
  • Decorator装饰角色:一般是一个抽象类,在属性里必然有一个private变量指向Component抽象构件。
  • ConcreteDecoratorA和ConcreteDecoratorB具体装饰角色:把最核心的东西装饰成其他东西。

抽象构件Component:

public abstract class Component { 
    //抽象的方法 
    public abstract void operate(); 
}

具体构件ConcreteComponent:

public class ConcreteComponent extends Component { 
    //具体实现 
    @Override 
    public void operate() { 
        System.out.println("do Something"); 
    } 
}

抽象装饰者Decorator:

public abstract class Decorator extends Component { 
    private Component component = null; 
    //通过构造函数传递被修饰者 
    public Decorator(Component _component){ 
        this.component = _component; 
    }
    //委托给被修饰者执行 
    @Override 
    public void operate() { 
        this.component.operate(); 
    } 
}

当然了,若只有一个装饰类,则可以没有抽象装饰角色,直接实现具体的装饰角色即可。

具体的装饰类ConcreteDecorator1~2:

public class ConcreteDecorator1 extends Decorator { 
    //定义被修饰者 
    public ConcreteDecorator1(Component _component){ 
        super(_component); 
    }
    //定义自己的修饰方法 
    private void method1(){ 
        System.out.println("method1 修饰"); 
    }
    //重写父类的Operation方法 
    public void operate(){ 
        this.method1(); 
        super.operate(); 
    } 
}

public class ConcreteDecorator2 extends Decorator { 
    //定义被修饰者 
    public ConcreteDecorator2(Component _component){ 
        super(_component); 
    }
    //定义自己的修饰方法 
    private void method2(){ 
        System.out.println("method2修饰"); 
    }
    //重写父类的Operation方法 
    public void operate(){ 
        super.operate(); 
        this.method2(); 
    } 
}

注意:原始方法和装饰方法的执行顺序在具体的装饰类是固定的,可以通过方法重载实现多种执行顺序

场景类Client:

public class Client { 
    public static void main(String[] args) { 
        Component component = new ConcreteComponent(); 
        //第一次修饰 
        component = new ConcreteDecorator1(component); 
        //第二次修饰 
        component = new ConcreteDecorator2(component); 
        //修饰后运行 
        component.operate(); 
    } 
}

装饰模式的优点

  • 装饰类和被装饰类可以独立发展,而不会相互耦合。
  • 装饰模式是继承关系的一个替代方案。
  • 装饰模式可以动态地扩展一个实现类的功能。

装饰模式的缺点

多层的装饰是比较复杂的。尽量减少装饰类的数量,以便降低系统的复杂度。

装饰模式的使用场景

  • 需要扩展一个类的功能,或给一个类增加附加功能。
  • 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
  • 需要为一批的兄弟类进行改装或加装功能,首选装饰模式。

装饰模式的实例

学校要求四年级的学生,必须将期末考试成绩单拿给父母签字才可以升五年级。那么 ,考的相对较差的同学,直接拿着原始成绩单,肯定免不了一顿“嘿嘿哈哈”。为了避免这种情况,我们就必须针对成绩单进行一下装饰。

(1)定义抽象类SchoolReportt

public abstract class SchoolReport {
	public abstract void report();	//成绩单
	public abstract void sign(String name);	//签名
}

(2)定义SchoolReportt的实现类FourthGradeSchoolRepor,FourthGradeSchoolRepor是最原始的成绩单及签名

import com.sfq.impl.SchoolReport;
public class FouthGradeSchoolReport extends SchoolReport {
	@Override
	public void report() {
		System.out.println("尊敬的XXX家长:");
		System.out.println("语文 66  数学67 英语68");
		System.out.println("                家长签名:        ");
	}
	@Override
	public void sign(String name) {
		System.out.println("家长签名为:" + name);
	}
}

(3)定义一个抽象装饰类,来实现原始的成绩单及签名

public abstract class Decorator extends SchoolReport {
	//首先知道是哪个成绩单
	private SchoolReport sr;
	//构造函数拿来成绩单
	public Decorator(SchoolReport sr) {
		this.sr = sr;
	}
	//看成绩单,实际看的还是FouthGradeSchoolReport中的成绩单
	@Override
	public void report() {
		this.sr.report();
	}
	//签名,实际签的还是FouthGradeSchoolReport中的签名
	@Override
	public void sign(String name) {
		this.sr.sign(name);
	}
}

(4)在原始成绩单之前装饰上最高成绩HignScoreDecorator 

import com.sfq.impl.Decorator;
import com.sfq.impl.SchoolReport;
public class HignScoreDecorator extends Decorator {
	public HignScoreDecorator(SchoolReport sr) {
		super(sr);
	}
	//先汇报最高成绩
	private void reportHignScore() {
		System.out.println("考试最高分:语文75,数学70,英语70");
	}
	@Override
	public void report() {
		this.reportHignScore();
		super.report();
	}
}

(5)在原始成绩后装饰上名次

import com.sfq.impl.Decorator;
import com.sfq.impl.SchoolReport;
public class SortDecorator extends Decorator {
	public SortDecorator(SchoolReport sr) {
		super(sr);
	}
	//汇报排名情况
	private void reportSort() {
		System.out.println("排名38");
	}
	@Override
	public void report() {
		super.report();
		this.reportSort();
	}
}

(6)场景类Father,父亲看成绩单,高兴后签名

import com.sfq.action.FouthGradeSchoolReport;
import com.sfq.action.HignScoreDecorator;
import com.sfq.action.SortDecorator;
import com.sfq.impl.SchoolReport;
public class Father {
	public static void main(String[] args) {
		//拿来原装成绩单
		SchoolReport sr = new FouthGradeSchoolReport();
		//加上最高分说明
		sr = new HignScoreDecorator(sr);
		//加上排名
		sr = new SortDecorator(sr);
		//看成绩单
		sr.report();
		//签名
		sr.sign("老王");
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥羊汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值