简单工厂(SimpleFactory)模式简介

简单工厂模式是最简单的模式了,也是我们打开教材的第一个模式.

一, 简单工厂模式的定义.

简单工厂模式是这样的:

建立1个工厂类, 这个类有1个静态方法, 根据条件(参数)的不同返回不同的同1个类族的对象.

也就是工厂的产品是对象.

但是这种些对象可以属于不同的类,

但是它们的类通常是属于同一超类或实现同一 接口的子类.

比如:   1个工厂类F,  它有1个静态方法getObj(有参数)

getObj可以返回类A1的对象a1, 也可以返回类A2 的对象a2. 但是通常A1 和 A2属于同1个类A.

二, 简单工厂模式的意义.

这里先写个总结. 后面再举例子详细解释

意义就是.

根据上面的例子

1. 当你让程序猿修改类A1, 不会暴露A2的代码. 方便项目管理

2. 当你想添加业务时, 只需要增加子类A3, 不用修改上层A的代码.  方便扩展

(项目中上层类可能用jar包发布, 或者你没有权限)

三, 例子

这个例子很简单, 就是做1个简单的计算器, 只有加法和剪发. 界面大概是这样的:

图已烂

简单来讲, 就是让User输入2个integer,  然后按button + 就是显示和, 按button "-" 就显示差

3.1 不使用任何模式

当然, 业务和界面代码分开是最基本的要求.

有些人是这样写的:

业务类: Operator1

public class Operation1 {
	private int i;
	private int j;
	
	public Operation1(int i, int j){
		this.i = i;
		this.j = j;
	}
	
	private int add(){
		return i + j;
	}
	
	private int del(){
		return i - j;
	}
	
	public int getResult(String symbol){
		switch(symbol){
			case "+": return add();
			case "-": return del();
		}
		
		return 0;
	}
}

界面代码是这样的:

private void BtnClicked_btnDel(){
			int i = Integer.parseInt(tb_i.getText());
			int j = Integer.parseInt(tb_j.getText());
			
			lblResult.setText("" + new Operation1(i,j).getResult("-"));
	}
}
private void BtnClicked_btnAdd(){
			int i = Integer.parseInt(tb_i.getText());
			int j = Integer.parseInt(tb_j.getText());
			
			lblResult.setText("" + new Operation1(i,j).getResult("+"));
	}
}


上面的写法是可行的. 但是扩展性不好.

假如我想增加1个button "*" 乘法,  那么我们必须修改类Operation1 添加1个方法mul(),(以及getResult())

这就导致两个问题.

1.暴露了加法和减法是如何实现的.

2. 有可能Operation类不能修改.

3.2 使用简单工厂(SimpleFactory)模式

定义1个抽象超类 Operation

public abstract class Operation {
    private int i;
    private int j;
    
    public int getI(){
        return i;
    }
    
    public int getJ(){
        return j;
    }
    
    public Operation(int i, int j){
        this.i = i;
        this.j = j;
    }
    
    public abstract int getResult();
}

那么它的子类就必须重写getResult方法.

定义加法类. OperationAdd

public class OperationAdd extends Operation{
	public OperationAdd(int i, int j) {
		super(i, j);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public int getResult(){
		return this.getI() + this.getJ();
	}
}

减法类OperationDel

public class OperationDel extends Operation{
	public OperationDel(int i, int j) {
		super(i, j);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public int getResult(){
		return this.getI() - this.getJ();
	}
}


好了, 这是再定义1个工厂类, 这个工厂的产品就是Operation的子类对象.

public class OperationFactory {
	public static Operation getOperationObj(int i, int j, String symbol){
		switch(symbol){
		case "+": return new OperationAdd(i, j);
		case "-": return new OperationDel(i, j);
		}
		
		return null;
	}
}

客户端关键代码:

private void BtnClicked_btnDel(){
			int i = Integer.parseInt(tb_i.getText());
			int j = Integer.parseInt(tb_j.getText());
			
			Operation oper = OperationFactory.getOperationObj(i,j,"-");
			lblResult.setText("" + oper.getResult());
	}

UML:

 

咋一看, 这里用到4个类, 分别是1个超类, 1个加法类, 1个减法类, 一个工厂类. 貌似更加复杂啦.

但是, 实际上它的可扩展性更好.

首先, 修改减法类, 不会暴露加法类.

其次, 很方便地增加乘法功能.   只需增加1个乘法类, 及修改工厂类.    即使其他3个类用jar包发布也没关系, 根本没必要修改它们.

四, 开放-封闭原则(open-closed principle)

有人问,  貌似在方法1里Operation1类里增加1个乘法方法不是更加方便吗?

方法2里需要增加1个新的类啊.

先不考虑你能不能修改基类的问题.

就如数据库表设计一样,   范式越高, 表就被分割得越多.

增加业务的话,  增加表是优于修改旧表(增加列)的.

设计模式同样,  如果要增加功能,   增加1个类, 比修改旧类要好.

因为这符合开放封闭原则.

所谓开放-封闭原则就是, 对扩展开放, 对修改封闭.

程序猿在做prj时, 往往做到大半时,  遇到User改需求了,   虽然需求改动看起来很小, 实际上对程序影响很大,  甚至要重新翻工.

发生这种痛苦的事情就是在程序设计时对扩展性考虑得不足.

在理想状态下, 我们做设计时, 尽量做到客户无论怎样修改或添加需求.

我们原来的代码(基类)都不用修改, 只需增加新的代码(新的子类)就ok了,  也就是让新代码去完成新的功能.

这就是所谓的开放-封闭原则.   在java设计模式中, 无论是哪个模式, 实际上都是为了实现这个原则而存在的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nvd11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值