Why use policy pattern references?

In the Android development process, we generally use the third-party framework, with the framework emerging in endlessly, with the development and expansion of the project, will not rule out the replacement of the framework, such as: log framework, picture framework, network framework and so on; Initially I will direct reference to the third party in the process of development framework, until framework need to be replaced, only to find that the workload is huge and meaningless of this process, need to be modified to use where framework has several dozens (if the project is big, far more than this number), then I will wake up, must cultivate architecture thought, The unmanageable implements the function and assumes that everything is ok. Later, in the learning process, I found that using the strategy mode can solve the problem of frame replacement in a friendly way, and the whole project frame can be easily changed by a single code.


    You can do this without using policy mode encapsulation.

    Some readers might think that there is no need to bother with the policy pattern, that they just need to re-wrap the framework so that changes can be made without affecting the rest of the code. For this idea, I use the Image framework Universal- image-loader as an example to briefly describe, paste a short code for clarity.

    /** / public class ImageLoaderUtils {private DisplayImageOptions mImageOptions; publicImageLoaderUtils() {/ / configuration UIL initialization ImageLoaderConfiguration configuration. = ImageLoaderConfiguration createDefault (this); ImageLoader.getInstance().init(configuration); mImageOptions = DisplayImageOptions.createSimple(); } // Default loading public static void loadImageView(Context Context, String imgUrl, ImageView view) { ImageLoader.getInstance().displayImage(imgUrl, view, mImageOptions); }}Copy the code


    The encapsulated utility class is demonstrated in an Activity as follows:

    Public class ExampleActivity extends AppActivity {private ImageView mIvPhoto; public class ExampleActivity extends appActivity {private ImageView mIvPhoto; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_test);
    
            mIvPhoto = findViewById(R.id.iv_cover);
            
            ImageLoaderUtils.loadImageView(this,"url",mIvPhoto); }}Copy the code

    If you need to use Glide to replace the current Universal image-Loader framework, modify the ImageLoaderUtils utility class directly, so that you do not need to modify all parts of the Universal image-Loader framework.

    /** * Public class ImageLoaderUtils {// Default load public static void loadImageView(Context context, String imgUrl, ImageView view) { Glide.with(context).load(imgUrl).into(view); }}Copy the code

    This process can replace the framework, and the workload is not large, but I think this method has some disadvantages, eliminate the old framework code, in case of future problems with the new framework, it is troublesome to deal with the work, to put it simply, this method of processing can not coexist two or more than two framework scheme, If you need to switch frames in a project, it clearly feels inflexible, so I think it is advisable to introduce a strategic pattern.


    Open the path of encapsulation

    As for strategic patterns, I will not describe them in detail here, but I will write an article on “strategic patterns” later.

    First, we define a policy interface to hold methods that frameworks will use in common, such as loading images by default, loading GIFs, and so on.

    /** * public interface BaseImageLoaderStrategy {/** * default way to load images * @param context * @param view view control * @param imgUrl Image URL */ void loadImage(Context Context, ImageView view, Object imgUrl); }Copy the code


    Step 2: Then write the implementation class. Here I use universal-image-loader as an example to write a simple implementation class.

    /** * UniversalLoaderStrategy implements BaseImageLoaderStrategy {private UniversalLoaderStrategy implements BaseImageLoaderStrategy DisplayImageOptions mImageOptions; /** * Initialize load configuration */ private voidinitOptions() { ImageLoaderConfiguration configuration = ImageLoaderConfiguration.createDefault(this); ImageLoader.getInstance().init(configuration); mImageOptions = DisplayImageOptions.createSimple(); } @Override public void loadImage(Context context, ImageView view, Object imgUrl) { ImageLoader.getInstance().displayImage(imgUrl, view, mImageOptions); }}Copy the code


    Once the implementation class is complete, the utility class that writes the last call completes the encapsulation.

    /** / public class ImageLoaderUtils {private BaseImageLoaderStrategy mImageLoaderStrategy; privateImageLoaderUtils() {
            //默认使用Universal-Image-Loader
            mImageLoaderStrategy = new UniversalLoaderStrategy();    }
    
       /**
        * 设置图片框架策略
        * @param strategy  图片框架策略
        **/
        public static void setImageLoaderStrategy(BaseImageLoaderStrategy strategy) {
            if(strategy ! = null) { mImageLoaderStrategy = strategy; Public static void loadImage(Context Context, ImageView view, Object imgUrl) { mImageLoaderStrategy.loadImage(context,view,imgUrl); }}Copy the code


    At this point, you have completed the initial encapsulation, using:

    ImageLoaderUtils.loadImage(context, imageView, imgUrl);Copy the code


    Initial encapsulation has been completed, but how to solve the problem of framework replacement seems to have not been mentioned. Don’t worry, brother. The bus will leave now. Hold on. If the project now uses the Glide framework, we need to write a simple Glide implementation class first. As follows:

    Public class GlideLoaderStrategy implements BaseImageLoaderStrategy {private RequestOptions mOptions; private ImageLoaderConfig mConfig; /** * Initialize load configuration */ private RequestOptionsgetOptions() {
        if(mOptions == null) { mOptions = new RequestOptions(); Moptions.error (McOnfig.geterrorpicres ()).placeholder(McOnfig.getplacepicres ()) // Download priority.priority(priority.normal) // Cache policy. DiskCacheStrategy (diskCacheStrategy.all); }returnmOptions; } @Override public void loadImage(Context context, ImageView view, Object imgUrl) {with(context).load(imgUrl).apply(getOptions()) .into(view); }}Copy the code


    Once Glide’s implementation class is out of the way, the framework can be replaced without affecting the rest of the code by calling the setImageLoaderStrategy method of ImageLoaderUtils.

    / / switch to Glide framework ImageLoaderUtils. SetImageLoaderStrategy (new GlideLoaderStrategy ());Copy the code

    This is probably the main idea, but encapsulation in real projects is not so simple. In order to describe this idea, I will paste the source address here. https://github.com/fansonq/ImageLoaderUtils interested readers may wish to download the reading, deeper understanding (source code comments).

    After looking at the picture frame encapsulation, we might as well try to encapsulate the log framework to understand and consolidate, the idea of mastery.

    If there are any mistakes or omissions in this article, please leave a message indicating correction; If there is something that is not clear enough, leave a comment and I will reply when I see it and communicate with you. If this article is helpful to you, please click “like” to support, and I will try to take time to share the knowledge points I think are good to you in the future.