策略模式下的Swing计算器实现
一、 设计说明:
策略模式:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
应用场景:
1、 需要使用ConcreteStrategy提供的算法。
2、 内部维护一个Strategy的实例。
3、 负责动态设置运行时Strategy具体的实现算法。
4、 负责跟Strategy之间的交互和数据传递。
优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
二、url类图:
三、过程实现
1、绘制界面:
我的界面比较简陋,主要是想练习策略模式,结果却是界面和逻辑处理用了更多的时间,而4个方法策略却用了一会儿。代码如下(没有注释,以后一定改掉这个坏习惯):
package com.forlink.strategy.frames;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.forlink.strategy.methods.Add;
import com.forlink.strategy.methods.Div;
import com.forlink.strategy.methods.Minus;
import com.forlink.strategy.methods.Mul;
import com.forlink.strategy.methods.Operate;
public class Body extends JFrame implements ActionListener {
private JTextField text = new JTextField();
private JButton b0 = new JButton("0");
private JButton b1 = new JButton("1");
private JButton b2 = new JButton("2");
private JButton b3 = new JButton("3");
private JButton b4 = new JButton("4");
private JButton b5 = new JButton("5");
private JButton b6 = new JButton("6");
private JButton b7 = new JButton("7");
private JButton b8 = new JButton("8");
private JButton b9 = new JButton("9");
private JButton clear = new JButton("C");
private JButton back = new JButton("←");
private JButton point = new JButton(".");
private JButton equals = new JButton("=");
private JButton add = new JButton("+");
private JButton minus = new JButton("-");
private JButton mul = new JButton("×");
private JButton div = new JButton("÷");
private JButton b10 = new JButton("±");
private JButton b11 = new JButton("M");
private JPanel p1 = new JPanel();
private JPanel p2 = new JPanel();
private boolean flag = false;//记录是否已经有运算过了;
private String f = "";
private JTextField t1 = new JTextField();
private JTextField t2 = new JTextField();
private String memory = "0";
public Body(){
this.setTitle("计算器");
this.setResizable(false);
this.setBounds(500, 300, 280, 260);
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
this.text.setEditable(false);
this.text.setColumns(12);
Font font = new Font("",20,25);
text.setFont(font);
text.setBackground(Color.white);
text.setForeground(Color.blue);
text.setHorizontalAlignment(JTextField.RIGHT);//设置对齐方式
text.setPreferredSize(new Dimension(280, 50));//设置高度
this.p1.add(this.text);
this.add(this.p1,"North");
GridLayout l = new GridLayout(4,5);
l.setVgap(5);
l.setHgap(5);
p2.setLayout(l);
this.add(p2,"Center");
p2.add(b1);
p2.add(b2);
p2.add(b3);
p2.add(clear);
p2.add(back);
p2.add(b4);
p2.add(b5);
p2.add(b6);
p2.add(add);
p2.add(minus);
p2.add(b7);
p2.add(b8);
p2.add(b9);
p2.add(mul);
p2.add(div);
p2.add(b0);
p2.add(point);
p2.add(equals);
p2.add(b10);
p2.add(b11);
/*add listeners*/
b0.addActionListener(this);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
b4.addActionListener(this);
b5.addActionListener(this);
b6.addActionListener(this);
b7.addActionListener(this);
b8.addActionListener(this);
b9.addActionListener(this);
add.addActionListener(this);
minus.addActionListener(this);
mul.addActionListener(this);
div.addActionListener(this);
point.addActionListener(this);
b10.addActionListener(this);
equals.addActionListener(this);
b11.addActionListener(this);
back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!flag){
String t = text.getText();
if(t.equals(f)){
f = "";
}
if(t.length()>0){
t = t.substring(0, t.length()-1);
}
text.setText(t);
}
}
});
clear.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
text.setText("");
t1.setText("");
t2.setText("");
f="";
flag = false;
}
});
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
JButton b = (JButton)e.getSource();
String bv = b.getText();
String tv = this.text.getText();
deal(bv,tv);
}
public void setValue(String tv, String f, boolean b){
if(b){
t1.setText(tv);
}
text.setText(f);
flag = false;
}
private void deal(String bv, String tv){
if(tv.length()>=18){
return;
}
if(tv.equals("error!")){
text.setText("");
t1.setText("");
t2.setText("");
f="";
flag = false;
}
if(bv.equals("+")||bv.equals("-")||bv.equals("×")||bv.equals("÷")){
if((tv.indexOf(".")+1==tv.length()&&tv.indexOf(".")!=-1) || f.length()>0 || tv.length()==0){
return;
}else{
boolean b = false;
if(t1.getText().length()<=0){
b = true;
}
if(bv.equals("+")){
f = "+";
setValue(tv, f, b);
}
if(bv.equals("-")){
f = "-";
setValue(tv, f, b);
}
if(bv.equals("×")){
f = "×";
setValue(tv, f, b);
}
if(bv.equals("÷")){
f = "÷";
setValue(tv, f, b);
}
}
}else if(bv.equals("M")){
if(tv.equals(f)){
text.setText(memory);
}else{
memory = tv;
}
}else if(bv.equals("=")){
if(!flag&&tv.length()>0&&f.length()>0&&!tv.equals(f)){
flag = true;
t2.setText(tv);
text.setText(compute(t1.getText(),t2.getText(),f));
t1.setText(text.getText());
f = "";
}
}else if(bv.equals("±")){
if(tv.length()>0&&flag==false){
if(tv.indexOf("-")==0){
text.setText(tv.substring(1));
}else if(tv.indexOf("-")==-1){
text.setText("-"+tv);
}
}
}else if(bv.equals(".")){
if(tv.indexOf(".")==-1){
if(tv.equals("")||tv.equals("-")){
return;
}else{
text.setText(link(bv,tv));
}
}else{
return;
}
}else{
if(!flag){
if(tv.equals(f)&&f.length()>0){
text.setText(bv);
}else{
if(tv.equals("0")||tv.equals("-0")){
return;
}
String v = link(bv,tv);
try{
Double.parseDouble(v);
text.setText(v);
}catch (Exception e){
System.out.println("输入出错");
return;
}
}
}
}
}
private String link(String bv,String tv){
return tv+bv;
}
private String compute(String t1,String t2,String f){
Operate o = null;
if(f.equals("+")){
o = new Operate(new Add());
}else if(f.equals("-")){
o = new Operate(new Minus());
}else if(f.equals("×")){
o = new Operate(new Mul());
}else if(f.equals("÷")){
o = new Operate(new Div());
}
double a = Double.parseDouble(t1);
double b = Double.parseDouble(t2);
String c = o.compute(a, b);
return c;
}
}
2、 程序入口定义:
public class Show {
public static void main(String[] args) {
Body b = new Body();
}
}
3、 策略接口定义:
public interface Imethod {
public String compute(double a, double b);
}
4、 操作者类定义:
public class Operate {
Imethod method;
public Operate(Imethod method){
this.method = method;
}
public String compute(double a, double b){
return this.method.compute(a, b);
}
}
5、 四个策略实现类:(需要说明的是,我的两个操作数是double型的,由于精度过高导致计算1-0.9=0.0999999999999998的情况,所以不得不强转为float了。)
加法:
public class Add implements Imethod {
public String compute(double a, double b) {
return (float)(a+b)+"";
}
}
减法:
public class Minus implements Imethod{
public String compute(double a, double b) {
// TODO Auto-generated method stub
return (float)(a-b)+"";
}
}
乘法:
public class Mul implements Imethod {
public String compute(double a, double b) {
return (float)(a*b)+"";
}
}
除法:
public class Div implements Imethod {
public String compute(double a, double b){
// TODO Auto-generated method stub
if(b==0){
return "error!";
}
return (float)(a/b)+"";
}
}
以上计算器的功能基本实现,其中M是记忆功能,此计算器漏洞比较多,中间逻辑处理比较乱,希望查阅到本文档的朋友能够将改进意见留下或者加我一起学习一起讨论。
效果图: