Android 原型设计模式

时间:2022-10-01 16:11:53

简介

原型模式是一个创建型的模式.原型就是应该有一个样板实例,我们可以从这个样板对象中复制出一个内部属性一致的对象,其实就是一个”克隆”,被复制的实例就是我们所称”原型”,这个原型是可定制的.主要是原型模式多用于创建复杂的或者[构造耗时]的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更加高效.

原型模式的定义

用原型模式指定创建对象的种类,并通过拷贝这些原型创建新的对象.

原型模式的使用场景

  • 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,这样也可以叫做保护性拷贝.
  • 通过new产生一个对象需要非常繁琐的数据准备或者访问权限.
  • 类初始化需要消化非常多的资源.

浅拷贝和深拷贝

浅拷贝,也称为影子拷贝,这份拷贝实际上并不是将原始文档的所有字段都重新构造了一份,而是副本文档的字段引用原始文档的字段.
深拷贝,就是不引用,创建一个全新的对象.

使用

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...............
}

}