Android 原型设计模式

简介

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

原型模式的定义

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

原型模式的使用场景

  • 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,这样也可以叫做保护性拷贝.
  • 通过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...............
    }

}
    原文作者:Tancker
    原文地址: https://blog.csdn.net/u010316858/article/details/50889541
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞