Android 原型设计模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010316858/article/details/50889541

简介

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

原型模式的定义

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

原型模式的使用场景

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

}

猜你喜欢

转载自blog.csdn.net/u010316858/article/details/50889541