装饰者模式(Decorator)实现与研究 - bei1999/work GitHub Wiki
定义
Attach additional responsibilities to an object dynamically keeping the same interface. Decoators provide a flexible alternative to subclassing for extending functionality.
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活
场景模拟
android 源码中context的使用
实现
- android 源码中context的使用
- java 中文件burrer使用
/**
* Interface to global information about an application environment. This is
* an abstract class whose implementation is provided by
* the Android system. It
* allows access to application-specific resources and classes, as well as
* up-calls for application-level operations such as launching activities,
* broadcasting and receiving intents, etc.
*/
public abstract class Context {
/**
* Same as {@link #startActivities(Intent[], Bundle)} with no options
* specified.
*
* @param intents An array of Intents to be started.
*
* @throws ActivityNotFoundException
*
* @see #startActivities(Intent[], Bundle)
* @see PackageManager#resolveActivity
*/
public abstract void startActivities(Intent[] intents);
@Nullable
public abstract ComponentName startService(Intent service);
public abstract boolean bindService(Intent service, @NonNull ServiceConnection conn,
@BindServiceFlags int flags);
/**
* Broadcast the given intent to all interested BroadcastReceivers. This
* call is asynchronous; it returns immediately, and you will continue
* executing while the receivers are run. No results are propagated from
* receivers and receivers can not abort the broadcast. If you want
* to allow receivers to propagate results or abort the broadcast, you must
* send an ordered broadcast using
* {@link #sendOrderedBroadcast(Intent, String)}.
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
*
* @see android.content.BroadcastReceiver
* @see #registerReceiver
* @see #sendBroadcast(Intent, String)
* @see #sendOrderedBroadcast(Intent, String)
* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
*/
public abstract void sendBroadcast(Intent intent);
}
Context 含有一些子类,我们看下ContextWrapper 这个子类
/**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context. Can be subclassed to modify behavior without changing
* the original Context.
*/
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
*/
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
...
}
调用了Context 的另一个子类ContextImpl
class ReceiverRestrictedContext extends ContextWrapper {
ReceiverRestrictedContext(Context base) {
super(base);
...省略部分代码
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context {
private final static String TAG = "ContextImpl";
private final static boolean DEBUG = false;
/**
* Map from package name, to preference name, to cached preferences.
*/
private static ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>> sSharedPrefs;
final ActivityThread mMainThread;
final LoadedApk mPackageInfo;
private final IBinder mActivityToken;
private final UserHandle mUser;
private final ApplicationContentResolver mContentResolver;
private final String mBasePackageName;
private final String mOpPackageName;
private final ResourcesManager mResourcesManager;
private final Resources mResources;
private final Display mDisplay; // may be null if default display
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
private final boolean mRestricted;
private Context mOuterContext;
private int mThemeResource = 0;
private Resources.Theme mTheme = null;
private PackageManager mPackageManager;
private Context mReceiverRestrictedContext = null;
private final Object mSync = new Object();
@GuardedBy("mSync")
private File mDatabasesDir;
@GuardedBy("mSync")
private File mPreferencesDir;
@GuardedBy("mSync")
private File mFilesDir;
@GuardedBy("mSync")
private File mNoBackupFilesDir;
@GuardedBy("mSync")
private File mCacheDir;
@GuardedBy("mSync")
private File mCodeCacheDir;
@GuardedBy("mSync")
private File[] mExternalObbDirs;
@GuardedBy("mSync")
private File[] mExternalFilesDirs;
@GuardedBy("mSync")
private File[] mExternalCacheDirs;
@GuardedBy("mSync")
private File[] mExternalMediaDirs;
private static final String[] EMPTY_STRING_ARRAY = {};
// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
static ContextImpl getImpl(Context context) {
Context nextContext;
while ((context instanceof ContextWrapper) &&
(nextContext=((ContextWrapper)context).getBaseContext()) != null) {
context = nextContext;
}
return (ContextImpl)context;
}
@Override
public AssetManager getAssets() {
return getResources().getAssets();
}
@Override
public Resources getResources() {
return mResources;
}
@Override
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
@Override
public Looper getMainLooper() {
return mMainThread.getLooper();
}
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
@Override
public void setTheme(int resId) {
if (mThemeResource != resId) {
mThemeResource = resId;
initializeTheme();
}
}
}
}
小结
通过上面的源码可以知道,ContextWapper 内部调用了使用代理方式包装了Context ,这样做的目的是灵活的修改和扩展原来的Context。既然提到context ,翻看源码context 抽象类所做的事情是跟其他组件的交互,比如activity,service,brocast 等,底层消息通讯就是ipc范畴了Acticvity 的父类是ContextThemeWrapper,ContextThemeWrapper 是对ContextWapper的theme 对应的扩展。
java 中文件burrer使用
常见的就是java 中对流的包装了
public class BufferedWriterTest {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("Buffered.txt");
/**
* 为了提高写入的效率,使用了字符流的缓冲区。
* 创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联。
*/
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区中的方法将数据写入到缓冲区中。
bufw.write("hello world !");
bufw.newLine();
bufw.newLine();
bufw.write("!hello world !");
bufw.write("!hello world !");
//使用缓冲区中的方法,将数据刷新到目的地文件中去。
bufw.flush();
//关闭缓冲区,同时关闭了fw流对象
bufw.close();
}
}
总结
上面的BufferedWriter 对原来的文件流内部建立了缓冲区域,加强了流的读写能力,装饰模式所做的事情就是如此,对于装饰者模式,它其实是一种包装,所以我更愿意称它为一种包装。