Java 设计模式情景分析——装饰模式
来源:互联网 发布:手机接单软件 编辑:程序博客网 时间:2024/05/16 01:41
转载请注明出处:http://blog.csdn.net/smartbetter/article/details/70834042
在现实生活中,人需要各式各样的衣物,不管你穿着怎样,但是,对于个人的本质来说是不变的,充其量只是在外面披上一层遮盖物而已,这就是装饰模式,装饰模式也称为包装模式,结构型设计模式之一,其使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种替代方案之一,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比于生成子类更为灵活。
1.装饰模式的使用情景
需要透明且动态地扩展类的功能时。
2.装饰模式的UML类图
3.装饰模式的通用模式代码
1.抽象组件 Component:
public interface Component { void operate();}
2.组件具体实现类 ConcreteComponent:
public class ConcreteComponent implements Component { @Override public void operate() { // 具体逻辑 }}
3.抽象装饰类 Decorator,职责就是为了装饰我们的组件对象,内部一定要有一个指向组件对象的引用:
public abstract class Decorator implements Component { private Component component; // 必须的构造方法 public Decorator(Component component) { this.component = component; } public void operate() { component.operate(); }}
4.装饰者的具体实现类 ConcreteDecoratorA、ConcreteDecoratorB(ConcreteDecoratorB 的代码和 ConcreteDecoratorA 本质无区别,只是实现不同,这里不再给出):
public class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } public void operate() { operateA(); super.operate(); operateB(); } // 自定义的装饰方法 public void operateA() { // 装饰方法逻辑 } // 自定义的装饰方法 public void operateB() { // 装饰方法逻辑 }}
5.编写测试类:
@Testpublic void test() throws Exception { // 构造被装饰的组件对象 Component component = new ConcreteComponent(); // 根据组件对象构造装饰者对象A并调用,此时相当于给组件对象增加装饰者A的功能方法 Decorator decoratorA = new ConcreteDecoratorA(component); decoratorA.operate(); Decorator decoratorB = new ConcreteDecoratorB(component); decoratorB.operate();}
4.Android系统源代码中的应用情景
Android系统源代码中的装饰模式也是常接触的,例如“上帝对象” Context 在我们装饰模式里就相当于抽象组件,而在其内部定义了大量的抽象方法,比如经常用到的 startActivity() 方法:
public abstract class Context { // 省略代码 public abstract void startActivity(@RequiresPermission Intent intent); public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle options); // 省略代码}
而其真正的实现是在 ContextImpl(Framework层) 中完成的:
class ContextImpl extends Context { // 省略代码 @Override public void startActivity(Intent intent) { warnIfCallingFromSystemProcess(); startActivity(intent, null); } @Override public void startActivity(Intent intent, Bundle options) { warnIfCallingFromSystemProcess(); if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) { throw new AndroidRuntimeException( "Calling startActivity() from outside of an Activity " + " context requires the FLAG_ACTIVITY_NEW_TASK flag." + " Is this really what you want?"); } mMainThread.getInstrumentation().execStartActivity( getOuterContext(), mMainThread.getApplicationThread(), null, (Activity) null, intent, -1, options); } // 省略代码}
这里 ContextImpl 就相当于组件具体实现类,其次我们知道,Activity 从类层次上来说本质是一个 Context,Activity 也并非直接 继承于 Context,而是继承于 ContextThemeWrapper:
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, WindowControllerCallback { // 代码省略}
而 ContextThemeWrapper 又继承于 ContextWrapper,ContextWrapper 才继承于 Context,为什么层次这么复杂呢?其实这里就是一个典型的装饰模式,ContextWrapper 就是装饰者,在 ContextWrapper 中有一个 Context 的引用:
public class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } // 代码省略 @Override public void startActivity(Intent intent) { mBase.startActivity(intent); } @Override public void startActivity(Intent intent, Bundle options) { mBase.startActivity(intent, options); } // 代码省略}
到这里已经可以看出装饰模式的模样了。
- Java 设计模式情景分析——装饰模式
- Java 设计模式情景分析——工厂模式
- Java 设计模式情景分析 ——单例模式
- Java 设计模式情景分析——建造者模式
- Java 设计模式情景分析——工厂方法模式
- Java 设计模式情景分析——策略模式
- Java 设计模式情景分析——观察者模式
- Java 设计模式情景分析——代理模式
- 基于东北F4的设计模式情景剧——第一幕 装饰模式(Decorator Pattern)
- java设计模式——装饰模式
- java设计模式——装饰模式
- java设计模式——装饰模式
- java设计模式——装饰模式
- Java设计模式——装饰模式
- Java 设计模式—装饰者模式
- Java设计模式—装饰模式
- java设计模式—装饰者模式
- 浅谈Java设计模式—-装饰模式
- H5学习笔记
- 集合框架-TreeSet保证元素唯一性和自然排序的原理和图解
- CentOS配置163源
- linux文件只有读、写,没有执行权限 怎么加
- C++ 返回指向数组指针的函数
- Java 设计模式情景分析——装饰模式
- activex 使用与注册
- populating-next-right-pointers-in-each-node-ii(二叉树每层用指针链接)
- iOS开发学习总结——数据存储和参数传递
- 图片理解数字签名和验签过程
- 校招必考:根据二叉树遍历序列确定二叉树
- 《深入浅出nodejs》异步I/O笔记(2)
- 分布式文件系统下的本地缓存
- CentOS 6.5 Install node.js