-
开闭原则;
-
单一职责;
-
依赖倒转;
一个比较常见的问题就是
if--else或者是switch语句的代码块,并不是不能使用,主要使其业务逻辑清晰。if-else的问题不是多,而是括号里逻辑,
一个好的程序员就应该把括号的逻辑用一个简单的函数或者对象等简单叙述,告诉别人你的逻辑是什么,使程序可读性好,调理清晰。
1、简单工厂模式
实现简单,思想易懂。
![](https://i-blog.csdnimg.cn/blog_migrate/b37593fb71216c559ae7938b3b075496.png)
例如一个四则运算的简单工厂模式实现:
//工厂生产的产品接口-计算两个数
public interface IOperation {
double caculate(double num1, double num2);
}
//加法的具体实现:
public class Add implements IOperation {
@Override
public double caculate(double num1, double num2) {
return num1 + num2;
}
}
//减法的具体实现:
public aspect Sub implements IOperation{
@Override
public double caculate(double num1, double num2) {
return num1 - num2;
}
}
//简单工厂实现:
//计算算法的工厂类实现-只能生产一种产品,就是计算两个数。
public class OperationFactory {
public static final int TYPE_ADD = 0;
public static final int TYPE_SUB = 1;
public static final int TYPE_MULTI = 2;
public static IOperation createOperation(int type) {
if (type == TYPE_ADD) {
return new Add();
} else if (type == TYPE_SUB) {
return new Sub();
} else if (type == TYPE_MULTI) {
return new Multi();
}
return null;
}
}
public class FactoryTest {
public static void main(String[] args) {
IOperation operation = OperationFactory.createOperation(OperationFactory.TYPE_ADD);
System.out.println("1 + 2 = " + operation.caculate(1, 2));
}
}
优点:
从上面可以看出,所有的产品都在一个工厂里生产,且这一个工厂只能生产一种产品,简单工厂实现了产品的生产和客户端使用的隔离;
缺点:
-
(1)、此时如果想增加一种产品,当需要新增加一种算法的时候需要修改工厂的代码,例如增加除法,就的修改工厂类的代码,不符合开闭原则;
-
(2)、且简单工厂中一个工厂生产了多种产品,也不符合单一职责原则;
适用场景:产品功能更新慢结构简单。
2、工厂模式
-
简单工厂模式对于每次新增产品功能都需要修改原来的代码,这是不可接受的,不符合开闭原则。为了代码的解耦和可扩展性,可以使用工厂模式。
-
实现:定义一个创建对象的接口,但让实现这个接口的类来决定实例化那个类,工厂方法让类的实例化推迟到子类。
![](https://i-blog.csdnimg.cn/blog_migrate/3319ad76cbee389db4934c688f477a54.png)
四则运算具体代码实现:
//工厂接口
public interface IFactory {
IOperation createOperation();
}
//加法工厂:
public class AddFactory implements IFactory {
@Override
public IOperation createOperation() {
return new Add();
}
}
//加法的实现:
public class Add implements IOperation {
@Override
public double caculate(double num1, double num2) {
return num1 + num2;
}
}
//减法工厂:
public class SubFactory implements IFactory {
@Override
public IOperation createOperation() {
return new Sub();
}
}
//减法的实现:
public aspect Sub implements IOperation{
@Override
public double caculate(double num1, double num2) {
return num1 - num2;
}
}
//工厂模式使用:
public class FactoryTest {
public static void main(String[] args) {
IFactory factory = new AddFactory();
IOperation operation = factory.createOperation();
System.out.println(" 1 + 2 =: " + operation.caculate(1, 2));
}
}
从上述代码中可以体会到:
-
(1)、工厂模式使工厂之间解耦,每种产品都由一个工厂生产,产品之间互不影响,符合单一职责原则。。
-
(2)、此时,如果想增加一个产品只需要增加一个工厂,然后此工厂负责生产新的产品,对原来的产品没有影响,也不需要修改原来的工厂类,符合开闭原则;
优点:
-
把对象的创建和使用的过程分开,对象创建和对象使用的职责解耦;
-
如果创建对象的过程复杂,创建过程统一到工厂里管理,既减少重复代码,也方便以后对创建过程的修改和维护;
-
当业务扩展时,只需要增加工厂子类,符合开闭原则;
缺点:工厂模式解决了产品结构的新增问题,但是不能解决不同等级产品的需求。
适用场景:产品种类更新迭代比较快的场景。例如if-else的场景就可以使用工厂模式来解耦,使其职责分明,简化业务代码,结构清晰,灵活扩展。
此例中,工厂模式虽然很好的实现了计算两位数不同算法的扩展,例如《加减》扩展到《加减乘除》能很快且灵活实现,但是对于同一种算法乘法而言,实现的时间和空间效率却不同,例如位运算的效率就比直接的加减乘除的效率高。如位运算x<<1,比x*2的效率高。对于《加减乘除》相同的结果不同算法又该如何实现呢?
3、抽象工厂模式
要实现同一种产品的不同质量等级,此时对于工厂模式来说,就不那么灵活了,需要修改源代码,例如基于策略模式,对于同样的《乘》法进行判断看具体使用位操作还是直接*2 的算法策略,这样又违背了开闭原则,所以此时又出现了抽象工厂模式。
抽象工厂模式解决核心的问题:解决不同工厂的相同产品不同的等级的需求
,
新增的是一个工厂,不是单个的产品。
缺点: 如果抽象工厂产品族中增加一个产品,那么其他的工厂都需要增加这个新的产品,因为增加的是工厂,工厂的生产产品类型都是一样的,只是效率不同;
适用场景:产品结构稳定,但是产品等级分类非常多;
![](https://i-blog.csdnimg.cn/blog_migrate/5a0b169e55289134b0f5bd37e89ae9a1.png)
还是以四则运算为例:
产品种类非常多且稳定,但相同产品有不同的等级要求,非常复杂,就可以使用抽象工厂模式。
-
其他算法- 加减乘除
-
位运算 - 加减乘除
-
直接计算- 加减乘除
虽然效率不同,但是它们都实现一样的加减乘除功能;
实例:
//抽象产品种类统一接口,所有的工厂都需要实现。
//抽象工厂的产品接口,统一规范,所有的工厂都的实现;
public interface ICalcAbstratFactory {
//加法
IOperation createAddOperation();
//减法
IOperation createSubOperation();
//除法
IOperation createDivOperation();
//乘法
IOperation createMultiOperation();
}
//位运算Bit工厂的实现:
public class BitFactory implements ICalcAbstratFactory {
@Override
public IOperation createAddOperation() {
return new BitAdd();
}
@Override
public IOperation createSubOperation() {
return new BitSub();
}
@Override
public IOperation createDivOperation() {
return new BitDiv();
}
@Override
public IOperation createMultiOperation() {
return new BitMulti();
}
}
//普通工厂实现加减乘除:
public class NormalFactory implements ICalcAbstratFactory {
@Override
public IOperation createAddOperation() {
return new NormalAdd();
}
@Override
public IOperation createSubOperation() {
return new NormalSub();
}
@Override
public IOperation createDivOperation() {
return new NormalDiv();
}
@Override
public IOperation createMultiOperation() {
return new NormalMulti();
}
}
//普通工厂加法的具体算法实现
public class NormalAdd implements IOperation {
@Override
public double caculate(double num1, double num2) {
return num1 + num2;
}
}
//抽象工厂的使用:
public class Test {
public static void main(String[] args) {
//普通运算实现工厂
ICalcAbstratFactory calcAbstratFactoryBit = new BitFactory();
calcAbstratFactoryBit.createAddOperation().caculate(1, 2);
//增加位运算实现工厂- 只需要实现抽象工厂的接口,不需要更改原来的工厂接口的代码;
ICalcAbstratFactory calcAbstratFactoryNormal = new NormalFactory();
calcAbstratFactoryNormal.createAddOperation().caculate(1, 2);
}
}
4、小结
简单工厂:
-
适用于产品迭代慢种类少的情况,同一个工厂生产不同的产品;
-
新增的是关系,需修改源代码,不符合开闭原则;
工厂模式:
-
适用于产品种类增减迭代快,不同工程生产不同的产品,
-
新增的是一个单一的工厂和产品,直接增加;
-
追求产品的创新种类;
抽象工厂:
-
适用于产品种类稳定,但是产品等级更新迭代快,不同的工厂生产同一个产品的情况;
-
新增的是一个工厂,直接增加;
-
追求产品等级质量;