Androidプロトタイプデザインモード
概要
プロトタイプモードは作成型のモードである.プロトタイプはテンプレートインスタンスがあるべきで、私たちはこのテンプレートオブジェクトから内部属性が一致するオブジェクトをコピーすることができて、実は1つの“クローン”で、コピーされたインスタンスは私たちが言う“プロトタイプ”で、このプロトタイプはカスタマイズすることができます.主にプロトタイプモードは、複雑なインスタンスまたは[構造に時間がかかる]インスタンスを作成するために使用されることが多い.この場合、既存のインスタンスをコピーすることで、プログラムの実行をより効率的に行うことができるからである.
プロトタイプモードの定義
プロトタイプモードで作成するオブジェクトの種類を指定し、これらのプロトタイプをコピーして新しいオブジェクトを作成する.
プロトタイプモードの使用シーンの1つのオブジェクトが他のオブジェクトへのアクセスを必要とする場合、各呼び出し元がその値を変更する必要がある場合、複数のオブジェクトをプロトタイプモードでコピーして呼び出し元として使用することも考えられ、これを保護コピーと呼ぶこともできる. newによって1つのオブジェクトを生成するには、非常に煩雑なデータ準備またはアクセス権限が必要である. 類の初期化は非常に多くの資源を消化する必要がある.
浅いコピーと深いコピー
薄いコピーは、影のコピーとも呼ばれ、実際には元のドキュメントのすべてのフィールドを再構築するのではなく、コピードキュメントのフィールドが元のドキュメントのフィールドを参照する.深いコピーとは、参照せずに新しいオブジェクトを作成することです.
使用
Androidソース実装
プロトタイプ実戦
プロトタイプモードは作成型のモードである.プロトタイプはテンプレートインスタンスがあるべきで、私たちはこのテンプレートオブジェクトから内部属性が一致するオブジェクトをコピーすることができて、実は1つの“クローン”で、コピーされたインスタンスは私たちが言う“プロトタイプ”で、このプロトタイプはカスタマイズすることができます.主にプロトタイプモードは、複雑なインスタンスまたは[構造に時間がかかる]インスタンスを作成するために使用されることが多い.この場合、既存のインスタンスをコピーすることで、プログラムの実行をより効率的に行うことができるからである.
プロトタイプモードの定義
プロトタイプモードで作成するオブジェクトの種類を指定し、これらのプロトタイプをコピーして新しいオブジェクトを作成する.
プロトタイプモードの使用シーン
浅いコピーと深いコピー
薄いコピーは、影のコピーとも呼ばれ、実際には元のドキュメントのすべてのフィールドを再構築するのではなく、コピードキュメントのフィールドが元のドキュメントのフィールドを参照する.深いコピーとは、参照せずに新しいオブジェクトを作成することです.
使用
public class Car implements Cloneable{
private String name;
private int mHeight;
private int mWidht;
//..................
@Overide
protected Car clone(){
try{
// Clone
Car car = (Car)super.clone();
car.name = this.name;
car.mHeight = this.mHeight;
car.mWidth = this.mWidth;
}(Exception e){
}
return null;
}
//..................
}
Androidソース実装
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
if (mSdkVersion <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
mContext = context;
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics = new DisplayMetrics();
mSettings = new Settings(context);// Settings
mSettings.addSharedUserLPw("android.uid.system", // id
Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
mDefParseFlags = 0;
mSeparateProcesses = separateProcesses.split(",");
Slog.w(TAG, "Running with debug.separate_processes: "
+ separateProcesses);
}
} else {
mDefParseFlags = 0;
mSeparateProcesses = null;
}
mInstaller = installer;// ServerThread , ping
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);// WINDOW_SERVICE
Display d = wm.getDefaultDisplay();//
d.getMetrics(mMetrics);
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
mHandlerThread.start();//
mHandler = new PackageHandler(mHandlerThread.getLooper());//PackageHandler
File dataDir = Environment.getDataDirectory();///data
mAppDataDir = new File(dataDir, "data");// /data/data
mAppInstallDir = new File(dataDir, "app");///data/app
mAppLibInstallDir = new File(dataDir, "app-lib");///data/app-lib
mAsecInternalPath = new File(dataDir, "app-asec").getPath();///data/app-asec
mUserAppDataDir = new File(dataDir, "user");///data/user
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");///data/app-private
sUserManager = new UserManagerService(context, this,
mInstallLock, mPackages);// UserManagerService
readPermissions();// ,
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
// Set flag to monitor and not change apk file paths when
// scanning install directories.
int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;//
if (mNoDexOpt) {
Slog.w(TAG, "Running ENG build: no pre-dexopt!");
scanMode |= SCAN_NO_DEX;
}
final HashSet<String> libFiles = new HashSet<String>();
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");///system/framework
mDalvikCacheDir = new File(dataDir, "dalvik-cache");///data/dalvik-cache
boolean didDexOpt = false;
/** * Out of paranoia, ensure that everything in the boot class * path has been dexed. */
String bootClassPath = System.getProperty("java.boot.class.path");// bootClassPath
if (bootClassPath != null) {// boot class
String[] paths = splitString(bootClassPath, ':');
for (int i=0; i<paths.length; i++) {
try {
if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {// ?
libFiles.add(paths[i]);
mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
didDexOpt = true;
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Boot class path not found: " + paths[i]);
} catch (IOException e) {
Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
+ e.getMessage());
}
}
} else {
Slog.w(TAG, "No BOOTCLASSPATH found!");
}
/** * Also ensure all external libraries have had dexopt run on them. */
if (mSharedLibraries.size() > 0) {//
Iterator<String> libs = mSharedLibraries.values().iterator();
while (libs.hasNext()) {
String lib = libs.next();
try {
if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
libFiles.add(lib);
mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
didDexOpt = true;
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
} catch (IOException e) {
Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ e.getMessage());
}
}
}
// Gross hack for now: we know this file doesn't contain any
// code, so don't dexopt it to avoid the resulting log spew.
libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");//framework-res.apk ,
/** * And there are a number of commands implemented in Java, which * we currently need to do the dexopt on so that they can be * run from a non-root shell. */
String[] frameworkFiles = mFrameworkDir.list();
if (frameworkFiles != null) {
for (int i=0; i<frameworkFiles.length; i++) {// /system/framework
File libPath = new File(mFrameworkDir, frameworkFiles[i]);
String path = libPath.getPath();
// Skip the file if we alrady did it.
if (libFiles.contains(path)) {// ,
continue;
}
// Skip the file if it is not a type we want to dexopt.
if (!path.endsWith(".apk") && !path.endsWith(".jar")) {//
continue;
}
try {
if (dalvik.system.DexFile.isDexOptNeeded(path)) {//
mInstaller.dexopt(path, Process.SYSTEM_UID, true);
didDexOpt = true;
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Jar not found: " + path);
} catch (IOException e) {
Slog.w(TAG, "Exception reading jar: " + path, e);
}
}
}
if (didDexOpt) {
// If we had to do a dexopt of one of the previous
// things, then something on the system has changed.
// Consider this significant, and wipe away all other
// existing dexopt files to ensure we don't leave any
// dangling around.
String[] files = mDalvikCacheDir.list();
if (files != null) {
for (int i=0; i<files.length; i++) {
String fn = files[i];
if (fn.startsWith("data@app@")
|| fn.startsWith("data@app-private@")) {
Slog.i(TAG, "Pruning dalvik file: " + fn);
(new File(mDalvikCacheDir, fn)).delete();
}
}
}
}
// Find base frameworks (resource packages without code).
mFrameworkInstallObserver = new AppDirObserver(// /system/framework
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM// apk,
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode | SCAN_NO_DEX, 0);//currentTime 0 SCAN_NO_DEX
// Collect all system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(// /system/app
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM // apk,
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all vendor packages.
mVendorAppDir = new File("/vendor/app");
mVendorInstallObserver = new AppDirObserver(// /vendor/app
mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
mVendorInstallObserver.startWatching();
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM // apk,
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles();
// Prune any system packages that no longer exist.// packages
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
if (!mOnlyCore) {
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
/* * If this is not a system app, it can't be a * disable system app. */
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {// app
continue;
}
/* * If the package is scanned, it's not erased. */
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
/* * If the system app is both scanned and in the * disabled packages list, then it must have been * added via OTA. Remove it from the currently * scanned package so the previously user-installed * application can be scanned. */// app disabled , ota , package ,
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
Slog.i(TAG, "Expecting better updatd system app for " + ps.name
+ "; removing system app");
removePackageLI(ps, true);
}
continue;
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
String msg = "System package " + ps.name
+ " no longer exists; wiping its data";
reportSettingsProblem(Log.WARN, msg);
removeDataDirsLI(ps.name);
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
//look for any incomplete package installations package
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
//clean up list
for(int i = 0; i < deletePkgsList.size(); i++) {
//clean up here
cleanupInstallFailedPackage(deletePkgsList.get(i));// package
}
//delete tmp files
deleteTempPackageFiles();//
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
mAppInstallObserver = new AppDirObserver(
mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
mAppInstallObserver.startWatching();// /data/app
scanDirLI(mAppInstallDir, 0, scanMode, 0);// package
mDrmAppInstallObserver = new AppDirObserver( //DRM, Digital Rights Management, :
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
mDrmAppInstallObserver.startWatching();// /data/app-private
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,// package
scanMode, 0);
/** * Remove disable package settings for any updated system * apps that were removed via an OTA. If they're not a * previously-updated app, remove them completely. * Otherwise, just revoke their system-level permissions. */
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
String msg;
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
+ " no longer exists; wiping its data";
removeDataDirsLI(deletedAppName);
} else {
msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for "
+ deletedAppName;
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
reportSettingsProblem(Log.WARN, msg);
}
} else {
mAppInstallObserver = null;
mDrmAppInstallObserver = null;
}
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
// If the platform SDK has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
// cases get permissions that the user didn't initially explicitly
// allow... it would be nice to have some better way to handle
// this situation.
final boolean regrantPermissions = mSettings.mInternalSdkPlatform
!= mSdkVersion;
if (regrantPermissions) Slog.i(TAG, "Platform changed from "
+ mSettings.mInternalSdkPlatform + " to " + mSdkVersion
+ "; regranting permissions for internal storage");
mSettings.mInternalSdkPlatform = mSdkVersion;
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL // package
| (regrantPermissions
? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
: 0));
// can downgrade to reader
mSettings.writeLPr();// /data/system/packages.xml
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
// Now after opening every single application zip, make sure they
// are all flushed. Not really needed, but keeps things nice and
// tidy.
Runtime.getRuntime().gc();
mRequiredVerifierPackage = getRequiredVerifierLPr();
} // synchronized (mPackages)
} // synchronized (mInstallLock)
}
プロトタイプ実戦
package com.softtanck;
public class User implements Cloneable{
public int age;
public String name;
public String phoneNum;
public Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
User user = null;
user = (User)super.clone(); // , .
return super.clone();
}
}
package com.softtanck;
public class Address {
public String city;
public String district;
public String street;
public Address(String aCity,String aDistrict,String aStreet){
// set...............
}
}