您的位置:首页 > 编程语言

代码整洁之道(三)-------------类

2015-11-25 21:28 183 查看
      遵循标准的Java约定,类应该从一组变量列表开始。如果有公共的静态常量。应该先出现,然后是私有静态变量,以及私有实体变量。很少会有公共变量。

公共函数应该在变量列表之后。我们喜欢把有某个公共函数调用的私有工具函数精随在该公共函数后面。这样符合了自顶向下原则,让程序读起来像一篇报纸文章。

 

(1)类应该短小

   跟函数一样,第一要义也是尽可能短小,但此短小非彼短小,对于函数我们透过行数来衡量,对于类我们则计算权责。

(2)单一权责原则

   单一权责原则(SRP)认为,类或模块应该有却只有一条加以修改的理由。该原则既给出了权责的定义,有是关于类长度的指导方针。SRP是OO设计中最为重要的概念之一,也是较为容易理解的和遵循的概念之一。

(3)保持内聚

  类应该只有少数实体变量。类中的每个方法都应该操作一个或多个这种变量,通常而言,方法操作的变量越多,就越黏聚到类上。如果一个类中的每个变量都被每个方法所使用,则该类就具有很高的内聚性。内聚性越高,意味着类中的方法和变量互相依赖、互相结合成一个整体。但有时有也不能一味的追求高内聚,还得视情况而定。

(4)开放--闭合原则(OCP)

开放--闭合原则(OCP)指的是类应该对扩展开放,对修改关闭。需求在变,代码也会跟着变。在OO编程中我们知道具体类包含实现细节,抽象类则只呈现概念。如果系统有经过好的解耦,也就更加灵活。

       

    来看看一个例子:这是我曾经写的一段代码,它是一个基类,需要被继承,它主要完成actionBar上的MenuItem的响应事件。menuItem有两个,一个是音量的设置,另一个是重启。很简单,但是代码太乱,需要整理。

public abstract class SencondBaseActivity extends BaseActivity {

   protected FragmentManager mFragmentManager;

   private ExitAppReceiver exitReceiver = new ExitAppReceiver();
 

   private List<MenuItem> menus = new  ArrayList<MenuItem>();
   
   // protected FrameLayout mContentLayout;
   // 当前服务端 Uri
   protected String uri = "";

   @SuppressLint("NewApi")
   @Override
   public void onMyBaseCreateView(Bundle savedInstanceState) {
 
      LogUtil.d("duanyl==============>getActionBar" + (actionBar == null));
       actionBar.showBack();
       initMenuItem();
       actionBar.addRightMenu(R.id.actionbar_menu, R.drawable.actionbar_setting_menu, menus);
       
      initRingDialog();
       
      onMyCreateView(savedInstanceState);
   }

   protected abstract void onMyCreateView(Bundle savedInstanceState);
 
    public void  initMenuItem(){
        MenuItem menu_volume = new MenuItem(R.id.menu_volume,R.drawable.actionbar_volume_menu,"音量");
       MenuItem menu_reboot = new MenuItem(R.id.menu_reboot,R.drawable.actionbar_reboot_menu,"重启");
       
       menus.add(menu_volume);
       menus.add(menu_reboot);
       
     }

    
    protected void onActionItemPressed(int viewId) {
       switch(viewId){
       case R.id.menu_volume:
          volumeDialog.show();
           break;
       case R.id.menu_reboot:
          reloadScutcheon();
           break;
       }
    }

    
   public AlertDialog volumeDialog;// 音量设置Dialog
   public String volume_value;// 音量设置的值

   /**
    * 初始化音量设置Dialog
    */
   public void initRingDialog() {
      AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
      final View dialogView = getLayoutInflater().inflate(
            R.layout.dialog_settingring, null);

      SeekBar volumnSeekBar = (SeekBar) dialogView
            .findViewById(R.id.seekbar_setting_volumn);
      final TextView volumnTxt = (TextView) dialogView
            .findViewById(R.id.txt_setting_volumn);
      volume_value = volumnTxt.getText().toString();
      volumnSeekBar.setMax(100);

      volumnSeekBar.setProgress(50);

      volumnSeekBar
            .setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

               @Override
               public void onStopTrackingTouch(SeekBar arg0) {

               }

               @Override
               public void onStartTrackingTouch(SeekBar arg0) {

               }

               @Override
               public void onProgressChanged(SeekBar arg0, int progress,
                     boolean fromUser) {
                  // 获取当前值
                  volumnTxt.setText(String.valueOf(progress));
                  volume_value = Integer.toString(progress);
               }
            });

      builder.setView(dialogView)
            // 添加button
            .setPositiveButton(R.string.enter,
                  new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int id) {

                        settingVolume(volume_value);

                        dialog.dismiss();
                     }

                  })
            .setNegativeButton(R.string.cancel,
                  new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                     }
                  });

      volumeDialog = builder.create();

   }

   /**
    * 异步设置音量
    * 
    * @param value
    */
   public void settingVolume(String value) {
      SetVolumeTask.getInstance().setVolume(uri, value, new VolumeListener() {

         @Override
         public void onSuccess(String msg) {
            // TODO Auto-generated method stub
            new SweetAlertDialog(mContext, SweetAlertDialog.SUCCESS_TYPE)
                  .setTitleText("Success").setContentText(msg).show();
         }

         @Override
         public void onFail(String error) {
            // TODO Auto-generated method stub

         }

      });
   }

   /**
    * 异步重启
    */
   public void reloadScutcheon() {
      ReloadTask.getInstance().Reload(uri, new ReloadListener() {

         @Override
         public void onSuccess(String msg) {
            // TODO Auto-generated method stub
            new SweetAlertDialog(mContext, SweetAlertDialog.SUCCESS_TYPE)
                  .setTitleText("Success").setContentText(msg).show();
         }

         @Override
         public void onFail(String error) {
            // TODO Auto-generated method stub

         }
      });
   }

}

一步一步来,首先可以看到有两个变量没有用到,所以删掉mFragmentManager,exitReceiver 。
 
 
然后,再把初始化音量设置的Dialog封装成类
/**
 * Created by Callanna on 2015/11/25.
 */
public class SetVolumeDialog extends AlertDialog implements View.OnClickListener {
    private Context mContext;

    public String volume_value;// 音量设置的值

    private SeekBar volumnSeekBar;

    private TextView volumnTxt;

    private SetVolumeDialog setVolumeDialog;

    private VolumeChangeListener mVolumeChangeListener;

    public SetVolumeDialog(Context context,VolumeChangeListener listener) {
        super(context);
              this.mContext = context;
        this.setVolumeDialog = this;
        this.mVolumeChangeListener = listener;
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.dialog_settingring, null);

        initSeekBarAndsetListener(view);

        setView(view);
    }

    private void initSeekBarAndsetListener(View view) {
        volumnSeekBar = (SeekBar) view.findViewById(R.id.seekbar_setting_volumn);
        volumnTxt = (TextView) view.findViewById(R.id.txt_setting_volumn);
        volume_value = volumnTxt.getText().toString();
        volumnSeekBar.setMax(100);

        volumnSeekBar.setProgress(50);

        volumnSeekBar.setOnSeekBarChangeListener(seekbarListener);
        view.findViewById(R.id.btn_change).setOnClickListener(this);
        view.findViewById(R.id.btn_cancel).setOnClickListener(this);
    }

    private SeekBar.OnSeekBarChangeListener seekbarListener = new SeekBar.OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar arg0) {
        }
        @Override
        public void onStartTrackingTouch(SeekBar arg0) {
        }
        @Override
        public void onProgressChanged(SeekBar arg0, int progress, boolean fromUser) {
            // 获取当前值
            volumnTxt.setText(String.valueOf(progress));
            volume_value = Integer.toString(progress);
        }
    };

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_change://change the volume
                mVolumeChangeListener.onChanged(volume_value);
                setVolumeDialog.dismiss();
                break;
            case R.id.btn_cancel:
                setVolumeDialog.dismiss();
                break;
        }
    }

    public interface VolumeChangeListener{
        void onChanged(String  value);
    }

}
 
封装好后,只要在回调一下就OK 了。
new SetVolumeDialog(mContext, new SetVolumeDialog.VolumeChangeListener() {
 @Override
 public void onChanged(String value) {
    settingVolume(value);
 }
}).show();
 
运行一下,发现没问题。而为了防止以后需求的变化,增加更多的MenuItem,是得该类变得拥挤。我还可以再封装一下。
/**
 * Created by duanyl on 2015/11/25.
 */
public class SecondMenuTask {
    private String current_manager_uri;
    private static SecondMenuTask  instance;
    private Context mContext;
    private SecondMenuTask(Context context){
        mContext = context;
        current_manager_uri = MyApplication.getInstance().getCurrent_manger().getUri();
    }

    public static SecondMenuTask getInstance(Context context){
        if(instance == null){
            instance = new SecondMenuTask(context);
        }
        return instance;
    }

    public void setVolume(String value){

            SetVolumeTask.getInstance().setVolume(current_manager_uri, value, new SetVolumeTask.VolumeListener() {

                @Override
                public void onSuccess(String msg) {
                    Toast.makeText(mContext,"Success",Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFail(String error) {
                    Toast.makeText(mContext, "fail", Toast.LENGTH_SHORT).show();
                }

            });
    }

    public void reloadScutcheon(){
        ReloadTask.getInstance().Reload(current_manager_uri, new ReloadTask.ReloadListener() {

            @Override
            public void onSuccess(String msg) {
                Toast.makeText(mContext, "Success", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFail(String error) {
                Toast.makeText(mContext, "fail", Toast.LENGTH_SHORT).show();
            }
        });
    }
 
而最终SecondBaseActivity也变的清爽多了。
public abstract class SencondBaseActivity extends BaseActivity {

   private List<MenuItem> menus = new  ArrayList<MenuItem>();

   @SuppressLint("NewApi")
   @Override
   public void onMyBaseCreateView(Bundle savedInstanceState) {
       actionBar.showBack();
       initMenuItem();
       actionBar.addRightMenu(R.id.actionbar_menu, R.drawable.actionbar_setting_menu, menus);
      onMyCreateView(savedInstanceState);
   }

   protected abstract void onMyCreateView(Bundle savedInstanceState);
 
    public void  initMenuItem(){
        MenuItem menu_volume = new MenuItem(R.id.menu_volume,R.drawable.actionbar_volume_menu,"音量");
       MenuItem menu_reboot = new MenuItem(R.id.menu_reboot,R.drawable.actionbar_reboot_menu,"重启");
       
       menus.add(menu_volume);
       menus.add(menu_reboot);
       
     }

    
    protected void onActionItemPressed(int viewId) {
       switch(viewId){
       case R.id.menu_volume:
          new SetVolumeDialog(mContext, new SetVolumeDialog.VolumeChangeListener() {
             @Override
             public void onChanged(String value) {
               SecondMenuTask.getInstance(mContext).setVolume(value);
             }
          }).show();
           break;
       case R.id.menu_reboot:
          SecondMenuTask.getInstance(mContext).reloadScutcheon();
           break;
       }
    }
}

   整洁的、好的代码不是一下子就写出来的,而是从最开始的可以工作,把大概的逻辑与算法理清,然后我们在一点一点改动,每做一次修改,编译运行一次,通过后再修改。一小步接一小步的使代码简洁利落。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  代码重构 android