Android Design Patterns appearance mode actually used in the project summary

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/jun5753/article/details/89846539

Foreword

Appearance very high frequency mode in development. We often use the basic third-party and open source library will use the facade pattern. By the appearance of a class makes the interface of the whole system is only a unified high-level interface, which helps reduce user costs, but also shields the user a lot of implementation details, the project easier to maintain.

When using a third-party SDK and open source library Probably the biggest idea is the use of packaging, packaging third-party API, at the same time may also be used in other design patterns such as policy mode, easy to replace third-party SDK at any time.

This article will look further in-depth summary mode of use in the project from the theory and practice.

Define the appearance mode

Appearance Model (Facade Pattern) mode known facade.

Its internal communication with the external request through a subsystem must be a unified object. Facade pattern provides a high-level interface, such that the subsystem easier to use.

Appearance pattern usage scenarios

  1. In the early stages of the design, the two different layers separated;
  2. During the development phase, subsystems, often because of the continuing evolution of reconstruction becomes more and more complex, and will have a lot of small class Most models use, this is a good thing, but also call them to an external user program creates difficulties of use, increased Facade appearance can provide a simple interface to reduce the dependency between them.
  3. When maintaining a large legacy system, the system may have been very difficult to maintain and expand, but because it contains a very important function, the new requirements development must rely on it.

UML class diagram appearance model

Here Insert Picture Description

Character introduction

  • Client: The client program.
  • Facade: Foreign unified portal, the appearance of the object.
  • SubSystemA: Subsystem A.
  • SubSystemB: Subsystem B.
  • SubSystemC: Subsystem C.
  • SubSystemD: D. Subsystem

Do not use the appearance of objects

Here Insert Picture Description
From the figure can be seen after this unified interface, the client and each subsystem interacts no appearance after class, increase the cost of the caller, the project has also increased maintenance costs.

Simple example of the appearance patterns to achieve

Life looks similar pattern mainly reflected in the structure of the central dispatch organizations, such as subway control center, the company's project manager, software company's technical team leader, and so on. Also for example, a TV remote control, television controls the switch machine, the player, sound regulation, another example mobile phones, set-in-one thousands like.

Below the process of software development technology leader (Leader), for example, be implemented in code.

1. The developer is responsible for development tasks.

/**
 * 开发人员
 */
class Developer {
    fun develop(name: String) {
        println("开发任务:$name")
    }
}

2. testers responsible for testing needs.

/**
 * 测试人员
 */
class Tester {

    fun test(name: String) {
        println("测试任务:$name")
    }
}

3. Product Manager (PM) responsible for providing demand, but also to follow up on the line of project development, testing and projects. The project ground.

/**
 * 产品经理, 对接开发和测试
 */
class ProductManager {
    private val developer = Developer()
    private val tester = Tester()

    fun demand(name: String) {
        println("提需求:$name")
        developer.develop(name)
        tester.test(name)
    }
}

Test code:

fun main() {
    val demander = ProductManager()
    demander.demand("开发一个跟淘宝一样的系统")
}
打印结果:
提需求:开发一个跟淘宝一样的系统
开发任务:开发一个跟淘宝一样的系统
测试任务:开发一个跟淘宝一样的系统

Only three color than the above (development, and testing requirements), the above code is not introduced into the model appearance.

Small company, the boss is basically flat project communication management, direct and develop, test communication, not too much organizational hierarchy. The initial project, this low-cost, but also to ensure that the project landing. But by the late development, the project is complicated, when requirements change frequently, standardized project is particularly important. Then the introduction of the development team leader (Leader) becomes very urgent, Leader directly and product requirements, testing and development staff to communicate, control the progress of the entire development process, can effectively enhance the development efficiency.

Let's look at how to introduce the code base before the appearance mode on.

Start by adding a role (Leader), equivalent to the charge of communication and coordination and progress of the entire development process of the control.

/**
 * 技术组长 Leader (统一的外观类)
 * Leader负责统一协调开发资源,内部资源的协调不需要外部知道
 */
class Leader {
    private val developer = Developer()
    private val tester = Tester()

    fun processDemand(name: String) {
        developer.develop(name)
        tester.test(name)
    }
}

Product Manager (PM) work improved. Prior to frequent communication develop and test two roles, and now the main communication Leader on it.

/**
 * 产品经理直接对接技术组长Leader
 */
class ProductManager2 {
   private val leader = Leader()

    fun demand(name: String) {
      leader.processDemand(name)
    }
}

Test code:

fun main() {
    val demander = ProductManager2()
    demander.demand("开发一个跟微信一样的系统")
}
//打印结果:
提需求:开发一个跟微信一样的系统
开发任务:开发一个跟微信一样的系统
测试任务:开发一个跟微信一样的系统

This is our appearance model, our technical team leader (Leader) is a symbol of the facade pattern, provided he receives specialized external demand service, then arrange the needs of students to develop and test students to ensure completion.

Android appearance model implemented in the source code

In the development process, Context is the most important type. It encapsulates many important operations, such startActivity (), sendBroadcast (), etc., is almost unified entrance for application developers to operate. Context is an abstract class that only defines the abstract interface, the true realization in ContextImpl class. It is the appearance of class today we want to analyze.

When the application starts, it first fork a child process, and calls ActivityThread.main method to start the process. ActivityThread will build the Application object, and then Activity, ContextImpl associate, and then call onCreate Activity of onStart, onResume the Activity function up and running. We take a look at the relevant code:

private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
		// 代码省略

        // 1、创建并且加载Activity,调用其onCreate函数
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            // 2、调用Activity的onResume方法,使Activity变得可见
            handleResumeActivity(r.token, false, r.isForward);

        }
    }

     private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
		// 代码省略

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            // 1、创建Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            r.intent.setExtrasClassLoader(cl);
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            // 2、创建Application
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (activity != null) {
                // ***** 构建ContextImpl  ****** 
                ContextImpl appContext = new ContextImpl();
                appContext.init(r.packageInfo, r.token, this);
                appContext.setOuterContext(activity);
                // 获取Activity的title
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mConfiguration);
            
                 // 3、Activity与context, Application关联起来
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstance,
                        r.lastNonConfigurationChildInstances, config);
				// 代码省略

                // 4、回调Activity的onCreate方法
                mInstrumentation.callActivityOnCreate(activity, r.state);
           
                // 代码省略
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
      
        }

        return activity;
    }


    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
   
        unscheduleGcIdler();

        // 1、最终调用Activity的onResume方法
        ActivityClientRecord r = performResumeActivity(token, clearHide);
        // 代码省略
        // 2、这里是重点,在这里使DecorView变得可见
        if (r.window == null && !a.mFinished && willBeVisible) {
                // 获取Window,即PhoneWindow类型
                r.window = r.activity.getWindow();
                // 3、获取Window的顶级视图,并且使它可见
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                // 4、获取WindowManager
                ViewManager wm = a.getWindowManager();
                // 5、构建LayoutParams参数
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    // 6、将DecorView添加到WindowManager中,最终的操作是通过WindowManagerService的addView来操作
                    wm.addView(decor, l);
                }
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }
            // 代码省略
    }

 public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide) {
        ActivityClientRecord r = mActivities.get(token);
       
        if (r != null && !r.activity.mFinished) {
                try {
                // 代码省略
                // 执行onResume
                r.activity.performResume();
				// 代码省略
            } catch (Exception e) {
   
            }
        }
        return r;
    }

Activity after the start, Android has provided us with a unified operating system entry services, namely Activity itself. These efforts are not implemented Activity own, but will operate mBase objects entrusted to Activity parent ContextThemeWrapper achieve this object class is ContextImpl (performLaunchActivity method is constructed ContextImpl ()).

class ContextImpl extends Context {
    private final static String TAG = "ApplicationContext";
    private final static boolean DEBUG = false;
    private final static boolean DEBUG_ICONS = false;

    private static final Object sSync = new Object();
    private static AlarmManager sAlarmManager;
    private static PowerManager sPowerManager;
    private static ConnectivityManager sConnectivityManager;
    private AudioManager mAudioManager;
    LoadedApk mPackageInfo;
    private Resources mResources;
    private PackageManager mPackageManager;
    private NotificationManager mNotificationManager = null;
    private ActivityManager mActivityManager = null;
    
	// 代码省略
    
        @Override
    public void sendBroadcast(Intent intent) {
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            ActivityManagerNative.getDefault().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, false, false);
        } catch (RemoteException e) {
        }
    }
    
    
        @Override
    public void startActivity(Intent intent) {
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
    }
    
    
        @Override
    public ComponentName startService(Intent service) {
        try {
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()));
            if (cn != null && cn.getPackageName().equals("!")) {
                throw new SecurityException(
                        "Not allowed to start service " + service
                        + " without permission " + cn.getClassName());
            }
            return cn;
        } catch (RemoteException e) {
            return null;
        }
    }
    
        @Override
    public String getPackageName() {
        if (mPackageInfo != null) {
            return mPackageInfo.getPackageName();
        }
        throw new RuntimeException("Not supported in system context");
    }
}

You can see, there are many objects inside ContextImpl xxxManager class, which is what we said above, the role of the various subsystems. Internal ContextImpl encapsulates the operating system level, and some features, while the subsystem is not achieved, but also provides an interface to the access subsystem, such as acquisition of ActivityManager getActivityManager method.

For example, we want to start an Activity, we call that startActivity method, the internal functions are implemented Instrumentation is actually done. ContextImpl encapsulates this feature, so that the user does not need to know the information related to Instrumentation, startActivity used directly to complete the work. Other subsystems function is similar implementations, such as starting internal Service and send broadcast using ActivityManagerNative and so on. FIG ContextImpl structure is as follows:

Here Insert Picture Description
Appearance model is very simple, but the packaging operation subsystem, and exposing the interface allows users to use, avoids the need for the user to interact with a plurality of subsystems, the coupling degree is reduced, the complexity. If there is no package appearance mode, the user must know the details of the interaction between the various subsystems, subsystems will inevitably lead to the stability of tangled relationships, affect the system's complexity.

Appearance practice mode to use in the project

  1. Image loading load library ImageLoder, encapsulates the internal network requests, caching, load details several models of success or failure, and so on.
  2. Friends of the Union statistics SDKin MobclickAgentthe package of the internal details of the statistics and so on.

Advantages and disadvantages appearance model

advantage

  • Easy to use, using the appearance model need to know exactly the client implementation subsystem;
  • Reduce the coupling client subsystem, to facilitate embrace change;
  • Better access division level;

Shortcoming

  • Exterior expanded class interface. Since the subsystem interface has the appearance of class unified external exposure, making the appearance like APImore interfaces, increase user costs used to some extent;
  • In appearance without introducing an abstract class, adding new sub-class you may need to modify the appearance of the source code or client, contrary to the "on-off principle";

to sum up

The core idea is to model the appearance of the package, aimed at unified programming interface. To provide a unified structure by a high-level user interface for the APIentry, such that a user can type the whole system, thus reducing the cost of ownership, enhance the flexibility of the system.

References:

1. He Honghui, people love Android source code analysis and practical design pattern [M] Beijing: People's Posts and Telecommunications Press

Guess you like

Origin blog.csdn.net/jun5753/article/details/89846539
Recommended