Androidプロジェクトの実践--メール送信インタフェースのパッケージと設計

15631 ワード

本文はブロガーのオリジナル文章で、ブロガーの許可を得ずに転載してはならない.シリーズチュートリアル:Android開発のゼロからシリーズ
もし皆さんが間違ったところや何か良いアドバイスを見たら、コメントを歓迎します.
前言:この間、会社のサービス側は人手が不足していましたが、プロジェクトはあるプラットフォームのメール送信インタフェースを接続する必要がありました.そこで、私はこの任務を引き受けました.元のメールで送信されたツール類コードを見ると、いくつかのプラットフォームのメールインタフェースの方法が積み重なっていることがわかり、互いに方法名だけを区別し、ツール類全体が数百行のコードで、関連方法を呼び出しても元のコードを維持しても、新しいメールプラットフォームを統合しても非常に不便であることがわかり、オブジェクト向けの設計の知識を学びながら、メールツール類の再構築に着手することにした.今回は、市販されているいくつかの一般的なメールインタフェースを例に、このような単一機能(メール送信)についてお話ししますが、さまざまなシナリオ(マルチプラットフォーム)のツール類のパッケージ化過程があり、プロジェクト開発と機能統合に啓発されることを期待しています.
パッケージング前の準備
手を出す前に、このツールクラスをどのように設計するかを考える必要があります.まず、なぜパッケージ化するのかを明確にしなければなりません.
パッケージの目的
  • メールツールクラスを呼び出すユーザに使用コストをできるだけ低減させる
  • .
  • は、後続のメンテナンスツール類の開発者が他のメールプラットフォームをより容易に統合し、既存のコード
  • をメンテナンスできるようにする.
    第1の要求に従って、私は最終的にこのメールツールクラスを呼び出す時に1つの統一的な入り口しかないことを望んで、それから簡単に1つのパラメータを通じてメールプラットフォームを選択するだけで、このプラットフォームの要求に従って相応のパラメータを入力してメール送信の操作を完成して、そして返信データを取得することができます.各プラットフォームのパラメータ名が異なり、カスタマイズされた機能拡張が可能であることを考慮して、Builderモードを使用してツールクラスのエントリを設計することにしました.
    さらに2つ目の要件は、従来のようにすべてのメールプラットフォームインタフェースを同じツールクラスに配置し、様々な解析関数もここに配置すれば、メンテナンスが非常に面倒になり、新しいメールプラットフォームを統合することで未知のBUGを導入する可能性があるため、各プラットフォームのドッキングコードを隔離する必要がある.
    では、メールツール類がどのように開発されたかを分析した後、「上から下へ設計し、下から上へ実現する」という思想に基づき、各プラットフォームのメールインタフェースの統合から一歩一歩このツール類を実現し始めた.
    抽象統合メールプラットフォームインタフェース
    従来のメールツール類にはアリクラウド、網易クラウド、雲信などのプラットフォームのメール送信インタフェースが集積されており、それらの中にはpostを使ってデータ伝送しかできないものもあり、post、getの2つの方式も可能であるため、抽象化を行う際にはこの2つの伝送方式を考慮し、SMSModel抽象類を作成する必要がある.
    public abstract class SMSModel {
        public abstract String post(Map map);
        public abstract String get(Map map);
    }

    アリクラウドのメール送信インタフェースを例に、ALModelを新設してSMSModelを継承し、具体的な要求過程を実現する
    /**
     *        
     */
    public class ALModel extends SMSModel{
    
        @Override
        public String post(Map map){
            //         ...
            return result;
        }
    
        @Override
        public String get(Map map) {//        get      ,          
            return "    !      get  ";
        }
    
    }

    次にアリクラウドメールプラットフォームの開発ドキュメントに従い、入参リストに従ってSMSParameerを作成し、ユーザーがパラメータを注入しやすいようにする.
    public class SMSParameter {
    
        //      
        public static final String SMS_MODEL_AL = "AL";//       
    
        //         ,  :https://help.aliyun.com/document_detail/55284.html?spm=5176.doc55289.6.557.J43llA
        public static final String AL_KEYID = "AccessKeyId";
        public static final String AL_KEYSECRET = "AccessKeySecret";
        public static final String AL_PHONENUMBERS = "PhoneNumbers";//      
        public static final String AL_SIGNNAME = "SignName";//    
        public static final String AL_TEMPLATECODE = "TemplateCode";//    ID
        public static final String AL_TEMPLATEPARAM = "TemplateParam";//        JSON 
        public static final String AL_SMSUPEXTENDCODE = "SmsUpExtendCode";//       
        public static final String AL_OUTID = "OutId";//        
    }

    他のメールプラットフォームの統合もそうですが、余計なことは言いません.
    BuilderクラスとミドルウェアRequestクラスの構築を実現
    ユーザーは、私たちのパッケージツールクラスを使用する場合、メールインタフェースが具体的にどのように呼び出されているかを知る必要はありません.メールインタフェース呼び出しプロセスを隠すことで、ユーザー呼び出しエラーが発生した場合に発生する一連の問題を回避し、ユーザーの使用コストを効果的に削減することができます.そこで、SMSbuilderクラスを作成し、ユーザー呼び出しツールクラスのパラメータを管理および構成し、ツールクラスの自由な拡張と構築を実現します.SMSRequestクラスを作成してSMSbuilderとSMSMSModelを接続し、中間ブリッジとして機能します.
    まずSMSbuilderクラスを見て、ツールクラスを初期化するためのいくつかのパラメータを暫定的に設定し、列挙(ModelType)を使用してユーザーが選択できるメールプラットフォームを制限し、setModelTypeメソッドでユーザーの選択に基づいて対応するSMSModelをインスタンス化し、最後にbuild()メソッドを使用してツールクラスの初期化を完了すると、SMSRequestクラスをインスタンス化してメールインタフェースを呼び出す操作を実行します.SMSbuilderコードは次のとおりです.
    public abstract class SMSBuilder {
        public String builderType;//builder  ,  post get
        public String modelType;//         
        public Map map;//         
        public SMSModel smsModel;
    
        /**
         *     :
         * SMS_MODEL_AL(      )
         */
        public enum ModelType{
            SMS_MODEL_AL
        }
    
        public SMSBuilder() {}
    
        public SMSBuilder setModelType(ModelType modelType) {
            if (modelType != null) {
                switch (modelType) {
                case SMS_MODEL_AL:
                    this.modelType = SMSParameter.SMS_MODEL_AL;
                    smsModel = new ALModel();
                    break;
                default:
                    this.modelType = "";
                    break;
                }
            }
            return this;
        }
    
        public SMSBuilder addMapParams(Map map){
            if(this.map == null){
                this.map = map;
            }
            return this;
        }
    
        public SMSRequest build(){
            return new SMSRequest(this);
        }
    }

    SMSRequestクラスは、ユーザがSMSbuilderを使用して初期化したパラメータに基づいて、特定の呼び出しインタフェース操作(toRequest)を実行し、コードは以下の通りである.
    public class SMSRequest {
        private SMSModel smsModel;
        private String builderType;
        private String modelType;
        private Map paramsMap;
        private String result;
    
        private String errorMessage;
    
        public SMSRequest(SMSBuilder builder){
            builderType = builder.builderType;
            modelType = builder.modelType;
            paramsMap = builder.map;
            smsModel = builder.smsModel;
            result = "";
            errorMessage = modelType+":"+builderType;
    
            if(builder.modelType == null || builder.modelType.equals("")){
                result = builderType+"    !          ";
                return;
            }
            toRequest();
        }
    
        /**
         *         
         */
        public String execute(){
            return result;
        }
    
        private void toRequest(){
            if(paramsMap==null){
                result = errorMessage+"    !map    !";
                return;
            }
            if(builderType.equals("post")){
                result = smsModel.post(paramsMap);
            }else if(builderType.equals("get")){
                result = smsModel.get(paramsMap);
            }
        }
    }

    ここでは、最も基本的な機能構成を例に挙げるだけで、タイムアウトアラート、群発メール、非同期受信返信など、より多くの機能を拡張する必要がある場合は、これに基づいて変更することができます.
    ユーザー向けのSMSUtilsクラスの実装
    最後に,ユーザが直接接触するクラスSMSUtilsを見ると,コードは比較的簡単であるが,ここでは単一のモードを用いてSMSUtilsをインスタンス化し,PostBuilderとGetBuilderを定義してpostとget要求を区別し,具体的なコードは以下の通りである.
    public class SMSUtils {
    
        private volatile static SMSUtils mInstance;
    
        private SMSUtils(){}
    
        private static class SMSUtilsHolder{
            private static final SMSUtils mInstance = new SMSUtils();
        }
    
        public static SMSUtils getInstance(){
            return SMSUtilsHolder.mInstance;
        }
    
        public class PostBuilder extends SMSBuilder{
            public PostBuilder(){
                this.builderType = "post";
            }
        }
    
        public class GetBuilder extends SMSBuilder{
            public GetBuilder(){
                this.builderType = "get";
            }
        }
    
        public static PostBuilder post(){
            return getInstance().new PostBuilder();
        }
    
        public static GetBuilder get(){
            return getInstance().new GetBuilder();
        }
    }

    ツールクラス全体のカプセル化が完了すると,ユーザは後でメール送信インタフェースを呼び出す際に,次の例のように簡単に数行のコードを書くだけでよい.
    String result = "";
    Map map = new HashMap();
    map.put(SMSParameter.XXX,     );
    ...//            
    
    result = SMSUtils
            .post()// post():     post,get():     get
            .setModelType(ModelType.SMS_MODEL_AL)//       
            .addMapParams(map)//     map
            .build()//      
            .execute();
    System.out.println("result:"+result);

    ツールクラス全体のディレクトリ構造は以下の通りであり、SMSUnitTestはユニットテストに用いられ、modelディレクトリの下に各メールプラットフォームの具体的な実装クラスが格納され、parameterディレクトリは共通のパラメータ定数クラスを格納するために用いられ、utilsディレクトリはxml、json解析クラスなどの必要なツールクラスを格納するために用いられる.
    ツールクラス全体の紹介が終わり、最初に提案した2つのパッケージの目的に戻り、私たちのツールクラスはユーザーの使用コストを効果的に削減しましたか?何百行ものツールクラスで使用するメールインタフェースを探すよりも、そうだと思います.Builderモードチェーン構造の初期化プロセスは、ユーザーが私たちのツールクラスをよりスムーズに呼び出し、コードロジックが明確で、読みやすいようにします.では、メンテナンススタッフの開発コストを削減しましたか?新しいメールプラットフォームの統合を例にとると、メンテナンス担当者はmodelパッケージの下で新しいプラットフォーム実装クラスを作成し、SMSbuilderに対応するパラメータを構成するだけで、ツールクラスの結合度を大幅に低減し、複数の開発による衝突の可能性も低減します.あるプラットフォームのドッキングにBUGが発生した場合、対応する実装クラスでのみDEBUGが必要となる
    今期のブログはここで终わりました.私の个人的な能力が限られているので、まだよくできていないところがあります.もし皆さんが何かアドバイスがあれば、コメントを歓迎して、BUGを书いてからBUGを修复してこそ、もっと多くのことを学ぶことができます.