Androidプロトタイプデザインモード


概要
プロトタイプモードは作成型のモードである.プロトタイプはテンプレートインスタンスがあるべきで、私たちはこのテンプレートオブジェクトから内部属性が一致するオブジェクトをコピーすることができて、実は1つの“クローン”で、コピーされたインスタンスは私たちが言う“プロトタイプ”で、このプロトタイプはカスタマイズすることができます.主にプロトタイプモードは、複雑なインスタンスまたは[構造に時間がかかる]インスタンスを作成するために使用されることが多い.この場合、既存のインスタンスをコピーすることで、プログラムの実行をより効率的に行うことができるからである.
プロトタイプモードの定義
プロトタイプモードで作成するオブジェクトの種類を指定し、これらのプロトタイプをコピーして新しいオブジェクトを作成する.
プロトタイプモードの使用シーン
  • の1つのオブジェクトが他のオブジェクトへのアクセスを必要とする場合、各呼び出し元がその値を変更する必要がある場合、複数のオブジェクトをプロトタイプモードでコピーして呼び出し元として使用することも考えられ、これを保護コピーと呼ぶこともできる.
  • newによって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...............
        }
    
    }