工厂模式总结(零到三)
方便理解 在来一个例子
简单小作坊型工厂
下面的例子介绍了将产品抽象以后,提供生产工厂,对产品进行销售,接受用户的定制。
但是交由一个工厂来做,越来越多的产品是不是会不专业呢。
package simple; /** * @author Heaton * @date 2018/3/28 0028 22:56 * @describe 牛奶接口 */ public interface Milk { /** * @author Heaton * @date 2018/3/28 0028 22:52 * @param [] * @return java.lang.String * @describe 提供牛奶 */ public String getName(); }
package simple; import simple.Milk; /** * @author Heaton * @date 2018/3/28 0028 22:56 * @describe 特仑苏牛奶 */ public class Telunsu implements Milk { /** * @author Heaton * @date 2018/3/28 0028 22:56 * @param [] * @return java.lang.String * @describe 特仑苏方法 */ @Override public String getName() { return "特仑苏"; } @Override public String toString() { return "Telunsu{}"; } }
package simple; /** * @author Heaton * @date 2018/3/28 0028 23:33 * @describe 伊利 */ public class Yili implements Milk { @Override public String getName() { return "伊利"; } @Override public String toString() { return "Yili{}"; } }
package simple; /** * @author Heaton * @date 2018/3/28 0028 23:33 * @describe 蒙牛 */ public class MenNiu implements Milk { @Override public String getName() { return "蒙牛"; } @Override public String toString() { return "MenNiu{}"; } }
package simple; /** * @author Heaton * @date 2018/3/28 0028 22:56 * @describe 简单工厂 */ public class SimpleFactory { public Milk getMike(String name){ if("特仑苏".equals(name)){ return new Telunsu(); }else if("伊利".equals(name)){ return new Yili(); }else if("蒙牛".equals(name)){ return new MenNiu(); } return null; } }
package simple; /** * @author Heaton * @date 2018/3/28 0028 22:56 * @describe 工厂测试 */ public class SimpleFactoryTest { public static void main(String[] args) { //小作坊式生产模式 //用户本身不在关心生产过程,而只需要关心结果 //加入:特仑苏、伊利、蒙牛 成分比例都不同 SimpleFactory factory = new SimpleFactory(); System.out.println(factory.getMike("伊利")); System.out.println(factory.getMike("特仑苏")); System.out.println(factory.getMike("蒙牛")); } }
不专业,我们就把工厂也给抽象了。
package simple.StaticFactory; import simple.Milk; /** * @author Heaton * @date 2018/3/29 0029 15:24 * @describe 静态工厂 */ public interface StaticFactory { //生产产品的技能 Milk getMilk(); }
package simple.StaticFactory; import simple.MenNiu; import simple.Milk; import simple.Telunsu; /** * @author Heaton * @date 2018/3/29 0029 15:24 * @describe X */ public class MengNiuFactory implements StaticFactory{ @Override public Milk getMilk() { return new MenNiu(); } }
package simple.StaticFactory; import simple.Milk; import simple.Telunsu; /** * @author Heaton * @date 2018/3/29 0029 15:24 * @describe X */ public class TelunsuFactory implements StaticFactory{ @Override public Milk getMilk() { return new Telunsu(); } }
package simple.StaticFactory; import simple.MenNiu; import simple.Milk; import simple.Yili; /** * @author Heaton * @date 2018/3/29 0029 15:24 * @describe X */ public class YiLiFactory implements StaticFactory{ @Override public Milk getMilk() { return new Yili(); } }
package simple.StaticFactory; /** * @author Heaton * @date 2018/3/29 0029 15:29 * @describe 工厂方法设计模式测试 */ public class StaticFactoryTest { public static void main(String[] args) { //发现必须要让用户来选择工厂,如果客户不知道工厂就会出错。 StaticFactory staticFactory = new MengNiuFactory(); System.out.println(staticFactory.getMilk()); StaticFactory staticFactory1 = new YiLiFactory(); System.out.println(staticFactory1.getMilk()); StaticFactory staticFactory2 = new TelunsuFactory(); System.out.println(staticFactory2.getMilk()); } }
那么用上面的方法工厂模式我们可以发现,工厂倒是专业了,可是问题来了,用户要定制产品的时候,找哪个工厂呢?很懵逼
那么能不能有一个更好的解决呢
package simple.AbsFactory; import simple.Milk; /** * @author Heaton * @date 2018/3/29 0029 15:53 * @describe 对专业的所有工厂进行抽象 */ public abstract class AbstractFactory { //公共的逻辑,为什么不是借口呢,是为了方便统一的管理, //接口不能存储逻辑,而抽象类可以 //获得一个蒙牛牛奶 public abstract Milk getMenNiu(); //获得一个伊利牛奶 public abstract Milk getYili(); //获得一个特仑苏牛奶 public abstract Milk getTelunsu(); //获得一个三鹿牛奶 public abstract Milk getSanLu(); }
package simple.AbsFactory; import simple.MenNiu; import simple.Milk; import simple.StaticFactory.MengNiuFactory; import simple.StaticFactory.TelunsuFactory; import simple.StaticFactory.YiLiFactory; /** * @author Heaton * @date 2018/3/29 0029 15:57 * @describe 对专业的所有工厂进行抽象 */ public class MilkFactory extends AbstractFactory { @Override public Milk getMenNiu() { return new MengNiuFactory().getMilk(); //return new MenNiu(); //可以直接选择对象,而这里使用了混合开发(spring就是这种工厂) //用了抽象工厂和工厂方法两种设计模式。 } @Override public Milk getYili() { return new YiLiFactory().getMilk(); } @Override public Milk getTelunsu() { return new TelunsuFactory().getMilk(); } //添加一个三鹿奶粉,抽象工厂只需要升级API就可以了 //现在去实现类李添加一个三鹿牛奶 //在就是直接在抽象工厂里添加一个返回方法 //在实现这个方法重写 @Override public Milk getSanLu() { return new SanLu(); } }
package simple.AbsFactory; /** * @author Heaton * @date 2018/3/29 0029 15:55 * @describe X */ public class AbstractFactoryTest { public static void main(String[] args) { AbstractFactory factory = new MilkFactory(); //对于用户不需要自己而言就可以找到工厂,直接定制专业的牛奶咯。 //而用户就相当于只有选择权了,不需要输入,就不会报错咯 System.out.println(factory.getMenNiu()); System.out.println(factory.getYili()); System.out.println(factory.getTelunsu()); //添加三鹿奶粉 System.out.println(factory.getSanLu()); } }
package simple.AbsFactory; import simple.Milk; /** * @author Heaton * @date 2018/3/29 0029 16:07 * @describe 毒奶粉 */ public class SanLu implements Milk { @Override public String getName() { return "三鹿"; } @Override public String toString() { return super.toString(); } }
注意看注释,添加了三鹿牛奶,只是简单的升级了API,而达到让用户多出选择项,达到了设计模式的开闭原则,
扩展开放,修改关闭。(增加代码,并不一定代表修改)
总结一下
简单工厂模式:对产品抽象,用户可以找到工厂定制产品,但是并不能把产品专业化,做出来的东西可能就是冒牌的。
工厂方法模式:对产品和工厂都进行抽象,不同的工厂根据配比生成不同的产品,用户在找到工厂的时候会很苦恼,但是一旦
找到,做出来的东西就会很OK。
抽象工厂方法:抽象出一个大工厂,给用户提供选择工厂的权利(接受定制的工厂),做出用户满意的产品。但是,大工厂在
管理上会耦合很多业务,对于管理不太方便。
抽象工厂+工厂方法:可以使用户有选择的权利,并且把大工厂的业务进行划分,对其下属工厂进行管理,制造出好产品。
实际应用一下,做个简单计算器
package com.tzy.FactoryApp; /** * @author Heaton * @date 2018/5/6 22:45 * @describe 操作 */ public abstract class Operation { private double num1; private double num2; public double getNum1() { return num1; } public void setNum1(double num1) { this.num1 = num1; } public double getNum2() { return num2; } public void setNum2(double num2) { this.num2 = num2; } public abstract double getResult(); }
package com.tzy.FactoryApp; /** * @author Heaton * @date 2018/5/6 22:47 * @describe 添加操作 */ public class AddOperation extends Operation { public double getResult() { double result = this.getNum1() + this.getNum2(); return result; } }
package com.tzy.FactoryApp; /** * @author Heaton * @date 2018/5/6 22:50 * @describe 减法操作 */ public class SubtractionOperation extends Operation { public double getResult() { double result = this.getNum1() - this.getNum2(); return result; } }
package com.tzy.FactoryApp; /** * @author Heaton * @date 2018/5/6 22:46 * @describe 操作工厂 */ public interface OperationFactory { public Operation getOperation(); }
package com.tzy.FactoryApp; /** * @author Heaton * @date 2018/5/6 22:47 * @describe 添加操作工厂 */ public class AddOperationFactory implements OperationFactory{ public Operation getOperation() { return new AddOperation(); } }
package com.tzy.FactoryApp; /** * @author Heaton * @date 2018/5/6 22:47 * @describe 减法操作工厂 */ public class SubtractionOperationFactory implements OperationFactory{ public Operation getOperation() { return new SubtractionOperation(); } }
package com.tzy.FactoryApp; import java.util.Scanner; /** * @author Heaton * @date 2018/5/6 22:44 * @describe 计算器 */ public class FactoryAppTest { public static void main(String[] args) { //1.接受控制台输入 System.out.println("---计算器程序---"); System.out.println("输入第一个操作数"); Scanner scanner = new Scanner(System.in); String strNum1 = scanner.nextLine(); System.out.println("输入运算符"); String oper = scanner.nextLine(); System.out.println("输入第二个操作数"); String strNum2 = scanner.nextLine(); double result = 0; double num1 = Double.parseDouble(strNum1); double num2 = Double.parseDouble(strNum2); //2.进行运算 OperationFactory factory; Operation operation; if ("+".equals(oper)) { factory = new AddOperationFactory(); result = getMethod(factory,num1,num2); } else if ("-".equals(oper)) { factory = new SubtractionOperationFactory(); result = getMethod(factory,num1,num2); } //3.返回结果 System.out.println(strNum1 + oper + strNum2 + "=" + result); } public static double getMethod(OperationFactory factory,double num1,double num2){ Operation operation= factory.getOperation(); operation.setNum1(num1); operation.setNum2(num2); double result = operation.getResult(); return result; } }
您的资助是我最大的动力!
金额随意,欢迎来赏!