1.在界面下方有3个按钮,分别是亮度、色彩度、饱和度
2. 点击按钮,选中一个,上面用一个滚动条显示亮度、色彩度、饱和度的值,三个用同一个滚动条。
3.选中后,滑动滚动条,调节当前选择的亮度、色彩度、饱和度。(不用真调节相机,假实现即可,但需要考虑将来可能会实现,要预留实现接口)
4.考虑一下,上面的需求可能会变化的情况,比如可能会增加减少要调节的项目,每个调节项目调节时触发的动作会修改,代码要能够很方便扩展。请采用适合的设计模式解决
思路&设计:
首先,根据题目要求,按下不同的按钮,调节不同的项目,这可以使用状态模式来实现。具体来说,按钮按下相当于切换了状态,在不同的状态下具有不同的行为,如色彩状态调节色彩,亮度状态调节亮度。
其次,要求每个项目对应的算法可以调节,比如说色彩调节可以有3种算法来实现,而可能根据不同情况选择不同算法。这里就其实就是算法的封装,采用策略模式。
结构图如下:
代码如下:
状态相关代码:
package com.wbp.designmodelpractice2; import android.widget.TextView; // 抽象状态类 abstract class ButtonState { protected int progress = 50;// 滑动条位置 protected AdjustAlgo adjustAlgo; // 算法类 // 算法开始执行 abstract public void beginAdjust(); // 更新状态(包含算法执行) abstract public void update(); public void setAdjustAlgorithm(AdjustAlgo adjustAlgo) { this.adjustAlgo = adjustAlgo; } public void setProcess(int progress) { this.progress = progress; } public AdjustAlgo getAdjustAlgo() { return adjustAlgo; } public int getProcess() { return progress; } } // 亮度调节状态类:具体状态 class LumState extends ButtonState { TextView tv; // 后期可能还会添加其他状态相关组件 如 ImageView @Override public void beginAdjust() { // TODO Auto-generated method stub adjustAlgo.excute(progress); } @Override public void update() { // TODO Auto-generated method stub tv.setText(String.valueOf(progress)); beginAdjust(); } } // 色彩调节状态类:具体状态 class ColorState extends ButtonState { TextView tv; // 后期可能还会添加其他状态相关组件 如 ImageView @Override public void beginAdjust() { // TODO Auto-generated method stub adjustAlgo.excute(progress); } @Override public void update() { // TODO Auto-generated method stub tv.setText(String.valueOf(progress)); beginAdjust(); } } // 饱和度调节状态类:具体状态 class SaturaState extends ButtonState { TextView tv; // 后期可能还会添加其他状态相关组件 如 ImageView @Override public void beginAdjust() { // TODO Auto-generated method stub adjustAlgo.excute(progress); } @Override public void update() { // TODO Auto-generated method stub tv.setText(String.valueOf(progress)); beginAdjust(); } }
算法相关代码:
package com.wbp.designmodelpractice2; // 抽象算法类 abstract public class AdjustAlgo { abstract public void excute(int progress); } //抽象算法类 abstract class ColorAdjustAlgo extends AdjustAlgo{ abstract public void excute(int progress); } //抽象算法类 abstract class LumAdjustAlgo extends AdjustAlgo{ abstract public void excute(int progress); } //抽象算法类 abstract class SaturaAdjustAlgo extends AdjustAlgo{ abstract public void excute(int progress); } // 色彩调节算法类:具体算法 class ColorAdjustAlgoOne extends ColorAdjustAlgo { public void excute(int progress) { // 具体色彩调节算法 System.out.println("色彩--------------->算法 1"); } } // 色彩调节算法类:具体算法 class ColorAdjustAlgTwo extends ColorAdjustAlgo { public void excute(int progress) { // 具体色彩调节算法 System.out.println("色彩--------------->算法 2"); } } // 亮度调节算法类:具体算法 class LumAdjustAlgoOne extends AdjustAlgo { public void excute(int progress) { // 具体亮度调节算法 System.out.println("亮度--------------->算法 1"); } } // 亮度调节算法类:具体算法 class LumAdjustAlgoTwo extends AdjustAlgo { public void excute(int progress) { // 具体亮度调节算法 System.out.println("亮度--------------->算法 2"); } } // 饱和度调节算法类:具体算法 class SaturaAdjustAlgoOne extends AdjustAlgo { public void excute(int progress) { // 具体饱和度调节算法 System.out.println("饱和度--------------->算法 1"); } } // 饱和度调节算法类:具体算法 class SaturaAdjustAlgoTwo extends AdjustAlgo { public void excute(int progress) { // 具体饱和度调节算法 System.out.println("饱和度--------------->算法 2"); } }
客户端相关代码:
package com.wbp.designmodelpractice2; import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { SeekBar seekbar; Button btnLum; Button btnColor; Button btnSatura; TextView tvLum; TextView tvColor; TextView tvSatura; List<ButtonState> stateList = new ArrayList<ButtonState>(); // ButtonState state; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { // 界面初始化 seekbar = (SeekBar) findViewById(R.id.seekBar1); seekbar.setProgress(50); btnLum = (Button) findViewById(R.id.btnLum); btnLum.setTag(0); btnLum.setOnClickListener(this); btnColor = (Button) findViewById(R.id.btnColor); btnColor.setTag(1); btnColor.setOnClickListener(this); btnSatura = (Button) findViewById(R.id.btnSatura); btnSatura.setTag(2); btnSatura.setOnClickListener(this); // 新建所有状态,并设置其对应的算法 LumState lum = new LumState(); lum.tv = (TextView) findViewById(R.id.tvLum); lum.setAdjustAlgorithm(new LumAdjustAlgoOne()); stateList.add(lum); ColorState color = new ColorState(); color.tv = (TextView) findViewById(R.id.tvColor); color.setAdjustAlgorithm(new ColorAdjustAlgoOne()); stateList.add(color); SaturaState satura = new SaturaState(); satura.tv = (TextView) findViewById(R.id.tvSatura); satura.setAdjustAlgorithm(new SaturaAdjustAlgoTwo()); stateList.add(satura); state = (ButtonState) stateList.get(0); seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub // 应用算法 state.setProcess(progress); state.update(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub state = (ButtonState) stateList.get((Integer) arg0.getTag()); seekbar.setProgress(state.getProcess()); state.update(); } }
说明:
1、扩展项目只需要增加新的状态类即可,扩展项目对应的算法只需要增加新的算法类即可,扩展很方便,完全符合“开闭”原则。这里有一点要说明的是,扩展项目的时候不一定像本题这样只通过TextView来显示项目数值,实际很可能还要显示别的组件,比如说显示颜色块,能让人直观的感受颜色变化。这一点通过状态类的扩展也容易做到。
2、标准的状态模式增加新的状态类需要修改负责状态转换的源代码,所以对“开闭”原则的支持并不好,这里巧妙的采用了Button点击来切换状态,解决了这个问题。
3、关于设计模式的选择:刚接触到这个题目的时候看到项目和算法两个维度的变化,感觉应该用桥接模式。但是自己思考过后,认为用在这里并不恰当。桥接模式两个维度分别有M、N种变化,那么总变化数为M*N,而且这M*N种变化都有存在的意义。但是本题目不是这样的,比如说,将颜色算法用到亮度状态上,结果显然是不伦不类的。
4、关于设计模式的体会:其实23中设计模式也只是相当于一些例子罢了,最重要的还是面向对象设计的那7个设计原则。开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段。对于如何编写扩展性好的程序,我的经验是,类和接口的设计要功能简单,然后编程的时候针对接口编程,这样就很容易符合“开闭”原则了。
其他:
1、最近看到很多设计模式采用 配置文件+反射机制 ,扩展只需要增加相关类,修改配置文件即可,客户端完全不需要改动。感觉这也太牛了吧!!千方百计想用在本例中,但是最终还是做不到。最起码按钮以及按钮的响应得添加吧,这些内容的添加难道可以不修改客户端吗?求解啊%>_<%
2、感觉设计的并不好,希望路过的高人不吝赐教
版权声明:本文为博主原创文章,未经博主允许不得转载。