扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
装饰者模式
在科尔沁等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都做网站、成都网站制作 网站设计制作专业公司,公司网站建设,企业网站建设,品牌网站设计,全网整合营销推广,外贸网站建设,科尔沁网站建设费用合理。
1、意图: 动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。
2、适用环境
(1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
(2)处理那些可以撤消的职责。
(3)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的 子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
3、参与者
1.Component(被装饰对象的基类)
定义一个对象接口,可以给这些对象动态地添加职责。
2.ConcreteComponent(具体被装饰对象)
定义一个对象,可以给这个对象添加一些职责。
3.Decorator(装饰者抽象类)
维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。
4.ConcreteDecorator(具体装饰者)
具体的装饰对象,给内部持有的具体被装
饰对象,增加具体的职责。
4、类图
5、涉及角色
(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类
(2)具体组件:将要被附加功能的类,实现抽象构件角色接口
(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。
装饰者模式( )
装饰者模式的核心思想在于 无需将所有的逻辑 即 核心内容构建 HTML文本构造和HTTP头生成等 个功能模块粘合在一起实现 通过装饰者模式 可以将它们分解为 个几乎完全独立的组件 并在使用时灵活地进行装配 为实现这个功能 可以使用如图 所示的结构
图 装饰者模式示例
IPacketCreator即装饰接口 用于处理具体的内容 PacketBodyCreator是具体的组件 它的功能是构造要发布信息的核心内容 但是它不负责将其构造成一个格式工整 可直接发布的数据格式 PacketHTTPHeaderCreator负责对给定的内容加上HTTP头部 PacketHTMLHeaderCreator负责将给定的内容格式化成HTML文本 如图 所示 个功能模块相对独立且分离 易于系统维护
IPacketCreator的实现很简单 它是一个单方法的接口
public interface IPacketCreator {
public String handleContent() //用于内容处理
}
PacketBodyCreator用于返回数据包的核心数据
public class PacketBodyCreator implements IPacketCreator{
@Override
public String handleContent() {
return Content of Packet ; //构造核心数据 但不包括格式
}
}
PacketDecorator维护核心组件ponent对象 它负责告知其子类 其核心业务逻辑应该全权委托ponent完成 自己仅仅是做增强处理
public abstract class PacketDecorator implements IPacketCreator{
IPacketCreator ponent;
public PacketDecorator(IPacketCreator c){
cponent=c;
}
}
PacketHTMLHeaderCreator是具体的装饰器 它负责对核心发布的内容进行HTML格式化操作 需要特别注意的是 它委托了具体组件ponent进行核心业务处理
public class PacketHTMLHeaderCreator extends PacketDecorator{
public PacketHTMLHeaderCreator(IPacketCreator c) {
super(c)
}
@Override
public String handleContent() { //将给定数据封装成HTML
StringBuffer *** =new StringBuffer()
*** append( )
*** append( body )
*** append(ponent handleContent())
*** append( /body )
*** append( /\n )
return *** toString()
}
}
返回目录 Java程序性能优化 让你的Java程序更快 更稳定
编辑推荐
Java程序设计培训视频教程
J EE高级框架实战培训视频教程
J ME移动开发实战教学视频
Visual C++音频/视频技术开发与实战
Oracle索引技术
lishixinzhi/Article/program/Java/gj/201311/27823
java decaf是什么,让我们一起了解一下?
decaf是一般视觉识别的深度卷积刺激特征,decaf是一个开放源代码,实现了这些深层卷积激活特性,以及所有相关的网络参数,使视觉研究人员能够在一系列视觉概念学习范例中进行深层表征的实验。
那如何正确高效理解decaf让我们更好的认知和学习呢?
我们通过学习设计模式之装饰者模式来系统了解。
首先装饰者模式是动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
我们要以饮料为主体,然后在运行时以调料来“装饰”(decorate)饮料。比方说,如果顾客想要摩卡和奶泡深焙咖啡,那么,要做的是:
1、拿一个深焙咖啡(DarkRoast)对象
2、以摩卡(Mocha)对象装饰它
3、以奶泡(Whip)对象装饰它
4、调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。
但是如何“装饰”一个对象,而“委托”又要如何与此搭配使用呢?那就是把装饰者对象当成“包装者”,让我们看看这是如何工作的:
1、以DarkRoast对象开始。
2、顾客想要摩卡(Mocha),所以建立一个 Mocha对象,并用它将DarkRoast对象包(wrap)起来。Mocha对象是一个装饰者,它的类型“反映”了它所装饰的对象(本例中,就是 Beverage)。所谓的“反映”,指的就是两者类型一致。
所以Mocha也有一个cost()方法。通过多态,也可以把Mocha所包裹的任何Beverage当成DarkRoast是Beverage(因为Mocha是Beverage的子类
型)。
3、顾客也想要奶泡(Whip),所以需要建立一个Whip装饰者,并用它将Mocha对象包起来。别忘了,DarkRoast继承自Beverage,且有一个cost()方法,用来计算饮料价钱。Whip是一个装饰者,所以它也 反映了DarkRoast类型,并包括一Mocha 个cost()方法。
4、现在,该是为顾客算钱的时候了。通过调用最外圈装饰者(Whip)的cost()就可以办得到。Whip的cost()会先委托它装饰的对象(也就是Mocha)计算出价钱,然后再加上奶泡的价钱。
代码实现:
/** * @author fan_rc@suixingpay.com * @description 饮料抽象类 * @date 2019/9/17 20:53 */ public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } /** * cost方法是用来返回饮料的价钱(需在具体类中自己实现) * * @return */ public abstract BigDecimal cost();
装饰者模式用来扩展对象的功能,给对象添加不同的功能。
在io流中,比如
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("d:/text.txt"))));
这种对File类的包装,由内层到外层扩展输入流的功能,就是一个典型的装饰者模式。inputstream是被装饰对象,然后Fileinputstream、InputStream、BufferedReader都是它的装饰器,用来扩展它的功能!
DataInputStream bis = new DataInputStream(new BufferedInputStream(new FileInputStream("File")));
BufferedInputStream bis2 = new BufferedInputStream(new DataInputStream(new FileInputStream("File")));
BufferedInputStream添加了缓冲功能,请问,bis还有缓冲功能么?bis现在是DataInputStream类型的,bis2才是BufferedInputStream类型的,这是我学些IO的一个问题,为什么bis还有缓冲功能?
问题:动态给一个对象添加一些额外的职责
思考:可以修改这个类的源代码吗?
回答:可以
思考:那直接修改源代码就行了
问题:如果不可以修改呢?
思考:如果不可以修改源代码,那怎么添加?
回答:有一些类库可以直接修改编译后的class文件,但是这里不考虑
可以直接包含这个类的对象,如果这个类有实现某些接口,刚好某个需要添加额外智能的方法正好是其中一个方法,那就好办了
Son这个类的paint()方法需要添加一些额外的功能
package decorator;
public class Son implements Work {
public void paint() {
System.out.println("儿子用铅笔画好了一幅画。");
}
}
这个类不是实现了Work方法吗?那就好办了,新建一个类,继承Work接口:
package decorator;
public class Mother implements Work {
//被装饰者
private Work work;
public Mother(Work work) {
this.work = work;
}
private Mother() {}
public void paint() {
//妈妈装饰者做的职责
System.out.println("妈妈正在做给画上颜色前的准备工作。");
//被装饰者做的职责
work.paint();
//妈妈装饰者做的职责
System.out.println("妈妈给画上好了颜色。");
}
}
那个所谓的Work接口:
package decorator;
public interface Work {
public void paint();
}
你不是想让Son可以的paint方法多做点工作么?那我new出Mother类执行paint方法不就可以了吗
看代码就知道,其实这个装饰器模式并不怎么好用,每个需要装饰的类或者需要继承某个接口,这实在是一个限制
网上找的资料:
装饰模式(Decorator)
装饰模式又名包装(Wrapper)模式。
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
装饰模式通过创建一个包装对象,也就是装饰,来包裹真实的对象。
装饰模式以对客户端透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。
装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。
装饰模式把客户端的调用委派到被装饰类。装饰模式的关键在于这种扩展是完全透明的。
装饰模式的角色
抽象构件角色(Component):给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件角色(Concrete Component):定义将要接收附加责任的类。
装饰角色(Decorator):持有一个构件(Component)对象的引用,并定义一个与抽象构件接口一致的接口。
具体装饰角色(Concrete Decorator):负责给构件对象“贴上”附加的责任。
Java IO中的装饰模式
在IO中,具体构件角色是节点流,装饰角色是过滤流。
FilterInputStream和FilterOutputStream是装饰角色,而其他派生自它们的类则是具体装饰角色。
装饰模式的特点
装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。
装饰对象包含一个真实对象的引用(reference)。
装饰对象接收所有来自客户端的请求,它把这些请求转发给真实的对象。
装饰对象可以在转发这些请求之前或之后附加一些功能。
这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。
程序实例
public interface Component
{
public void doSomething();
}
这是抽象构件角色,是一个接口。具体构件角色实现这个接口:
public class ConcreteComponent implements Component
{
@Override
public void doSomething()
{
System.out.println("功能A");
}
}
装饰角色:
public class Decorator implements Component
{
private Component component;
public Decorator(Component component)
{
this.component = component;
}
@Override
public void doSomething()
{
component.doSomething();
}
}
其中包含了构件角色的引用,方法调用中利用构件角色的方法。
具体装饰角色(两个):
public class ConcreteDecorator1 extends Decorator
{
public ConcreteDecorator1(Component component)
{
super(component);
}
@Override
public void doSomething()
{
super.doSomething();
this.doAnotherThing();
}
private void doAnotherThing()
{
System.out.println("功能B");
}
}
public class ConcreteDecorator2 extends Decorator
{
public ConcreteDecorator2(Component component)
{
super(component);
}
@Override
public void doSomething()
{
super.doSomething();
this.doAnotherThing();
}
private void doAnotherThing()
{
System.out.println("功能C");
}
}
使用测试:
public class Client
{
public static void main(String[] args)
{
Component component = new ConcreteComponent();
Component component1 = new ConcreteDecorator1(component);
component1.doSomething();
System.out.println("-----------");
Component component2 = new ConcreteDecorator2(component1);
component2.doSomething();
}
}
输出:
功能A
功能B
-----------
功能A
功能B
功能C
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流