设想形式 | 简朴工场形式_玖富娱乐主管发布


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。按理说应当把书全都看完一遍,再最先写博客对照科学,会有对照周全的熟悉。 然则既然都决议要按纪律更新博客了,只能看完一个设想形式写一篇了。 也算是逼本身思索了,不是看完就过,最少得把代码本身都敲一遍。 刚最先能够写的对照浅易,更像是读书笔记,只能将来返来完美了。 空话烦琐到这,最先正题。 文章是以一个口试中,口试官请求写一个盘算器开首的。 巧的是,在之前的一次口试中,恰好口试官也问了这个题目,事先我并不克不及给出令人满意的谜底,只恨没有早点进修设想形式啊。 代码不光是要完成功用就完事了,还要斟酌硬朗性、复用性、可扩展性等等。 进修设想形式的意义也在于此,资助我们写出越发文雅的代码。   那末回到之前的题目,若是如今要你写一个盘算器的顺序,你会怎样写呢? 我的第一回响反映和书中的菜鸟一样,迥殊照样在口试中,时候紧急,固然是把功用完成了就OK,为何要斟酌那末庞杂,写一个要领直接搞定: (这里为了代码的简约性,暂时不斟酌用户不按范例输入,除零、浮点失精这类硬朗性题目。)
 1 package designpattern.staticfactorymethod;
 2 import java.util.Scanner;
 3 public class Calculator {
 4      public static void main(String[] args) {
 5            Scanner scanner = new Scanner(System.in);
 6            System.out.println("请输入一个数字");
 7            double num1 = scanner.nextDouble();
 8            System.out.println("请输入一个运算符: 、-、*、/");
 9            String operator = scanner.next();// 不克不及用nextLine(),会把上一个回车给吸取
10            System.out.println("请输入一个数字");
11            double num2 = scanner.nextDouble();
12            switch (operator) {
13            case " ":
14                 System.out.println(num1   num2);
15                 break;
16            case "-":
17                 System.out.println(num1 - num2);
18                 break;
19            case "*":
20                 System.out.println(num1 * num2);
21                 break;
22            case "/":
23                 System.out.println(num1 / num2);
24                 break;
25            default:
26                 break;
27            }
28            scanner.close();
29      }
30 }

最多把盘算的要领单拉出来:

package designpattern.staticfactorymethod;
import java.util.Scanner;
public class Calculator2 {
     public static void main(String[] args) {
           Scanner scanner = new Scanner(System.in);
           System.out.println("请输入一个数字");
           double num1 = scanner.nextDouble();
           System.out.println("请输入一个运算符: 、-、*、/");
           String operator = scanner.next();// 不克不及用nextLine(),会把上一个回车给吸取
           System.out.println("请输入一个数字");
           double num2 = scanner.nextDouble();
           switch (operator) {
           case " ":
                System.out.println(plus(num1, num2));
                break;
           case "-":
                System.out.println(minus(num1, num2));
                break;
           case "*":
                System.out.println(multiply(num1, num2));
                break;
           case "/":
                System.out.println(divide(num1, num2));
                break;
           default:
                break;
           }
           scanner.close();
     }
     static double plus(double num1, double num2) {
           return num1   num2;
     }
     static double minus(double num1, double num2) {
           return num1 - num2;
     }
     static double multiply(double num1, double num2) {
           return num1 * num2;
     }
     static double divide(double num1, double num2) {
           return num1 / num2;
     }
}
如许虽然运算要领能够复用,然则显现和运算放在一同,你说它是个工具类吧,也不是,显得有些不正经。 要我来改,我最多把运算要领单拉成一个工具类,就完毕了:
package designpattern.staticfactorymethod;
public class CalculatorUtil {
     static double plus(double num1, double num2) {
           return num1   num2;
     }
     static double minus(double num1, double num2) {
           return num1 - num2;
     }
     static double multiply(double num1, double num2) {
           return num1 * num2;
     }
     static double divide(double num1, double num2) {
           return num1 / num2;
     }
}
我发明本身用java写了这么长时候的代码,好歹是个面向工具的言语,然则封装用的很闇练,然则继续和多态险些就没有用过。 虽然《Thinking In Java》的作者说不克不及滥用继续: 然则完整不消也是有题目的。 书中写的例子对我蛮有启示的。 如果我须要增添一个运算开根(sqrt)运算,怎样办? 只能去改谁人工具类,然则这会带来题目。 起首,你增添一个要领,要让之前已写好的加减乘除要领一同介入编译,增添了你不小心影响到之前要领的风险。 其次,能够之前的要领含有敏感信息,你并没有权限看(这个题目我之前还真的从来没有思索过) 那应当怎样办? 自然是把一切的运算要领零丁放在一个类里,如许就相互之间不影响,想新增直接新增类就可以够了,不消看之前的代码。 第一回响反映是写成如许,只是纯真的写成零丁的类:(为了轻易显现,写成了内部类;一样为了简约setter、getter我就不写了)
package designpattern.staticfactorymethod;
import java.util.Scanner;
public class Calculator3 {
     public static void main(String[] args) {
           Scanner scanner = new Scanner(System.in);
           System.out.println("请输入一个数字");
           double num1 = scanner.nextDouble();
           System.out.println("请输入一个运算符: 、-、*、/");
           String operator = scanner.next();// 不克不及用nextLine(),会把上一个回车给吸取
           System.out.println("请输入一个数字");
           double num2 = scanner.nextDouble();
           Calculator3 calculator3 = new Calculator3();
           switch (operator) {
           case " ":
                System.out.println(calculator3.new Plus(num1, num2).calculate());
                break;
           case "-":
                System.out.println(calculator3.new Minus(num1, num2).calculate());
                break;
           case "*":
                System.out.println(calculator3.new Multiply(num1, num2).calculate());
                break;
           case "/":
                System.out.println(calculator3.new Divide(num1, num2).calculate());
                break;
           default:
                break;
           }
           scanner.close();
     }
     class Plus {
           double num1;
           double num2;
           Plus(double num1, double num2) {
                this.num1 = num1;
                this.num2 = num2;
           }
           double calculate() {
                return num1   num2;
           }
     }
     class Minus {
           double num1;
           double num2;
           Minus(double num1, double num2) {
                this.num1 = num1;
                this.num2 = num2;
           }
           double calculate() {
                return num1 - num2;
           }
     }
     class Multiply {
           double num1;
           double num2;
           Multiply(double num1, double num2) {
                this.num1 = num1;
                this.num2 = num2;
           }
           double calculate() {
                return num1 * num2;
           }
     }
     class Divide {
           double num1;
           double num2;
           Divide(double num1, double num2) {
                this.num1 = num1;
                this.num2 = num2;
           }
           double calculate() {
                return num1 / num2;
           }
     }
}
你会发明这几个类组织都是如出一辙的,我险些也是复制粘贴出来的,我们是否是能够提掏出一个配合的父类来?
package designpattern.staticfactorymethod;
public abstract class Calculate {
     double num1;
     double num2;
     Calculate() {
     }
     Calculate(double num1, double num2) {
           this.num1 = num1;
           this.num2 = num2;
     }
     public abstract double calculate();
}

详细运算子类们:

package designpattern.staticfactorymethod;
public class Plus extends Calculate {
     Plus() {
     }
     Plus(double num1, double num2) {
           super(num1, num2);
     }
     @Override
     public double calculate() {
           return num1   num2;
     }
}
package designpattern.staticfactorymethod;
public class Minus extends Calculate {
     Minus() {
     }
     Minus(double num1, double num2) {
           super(num1, num2);
     }
     @Override
     public double calculate() {
           return num1 - num2;
     }
}
package designpattern.staticfactorymethod;
public class Multiply extends Calculate {
     Multiply() {
     }
     Multiply(double num1, double num2) {
           super(num1, num2);
     }
     @Override
     public double calculate() {
           return num1 * num2;
     }
}
package designpattern.staticfactorymethod;
public class Divide extends Calculate {
     Divide() {
     }
     Divide(double num1, double num2) {
           super(num1, num2);
     }
     @Override
     public double calculate() {
           return num1 / num2;
     }
}
继续终究派上用场了,你会发明如许照样没办法运用父类,想要详细的运算照样得直接去实例化子类的工具,和提取父类之前没有甚么区别。   接下来,终究,本日的主题要进场了,简朴工场设想形式。 先上一个百度百科诠释: 简朴工场形式是属于 建立型形式,又叫做静态工场要领(Static Factory Method)形式,但不属于23种GOF设想形式之一。简朴工场形式是由一个工场工具决议建立出哪种产品类的实例。简朴工场形式是工场形式家属中最简朴有用的形式,能够明白为是分歧工场形式的一个特别完成。   简朴来讲,它就是用来建立工具的,假设有那末一家神奇的工场,甚么都能消费,你只要对它说你想要甚么,它就会给你消费出来,你并不须要体贴,工场内部详细是怎样消费的。像如许:

固然现实代码中,不克不及像上面如许天马行空,术业照样要有专攻的,好比一个工场特地消费林林总总的女朋友,额。。

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-

好比iphon的工场特地消费种种型号的ipone。

把这个头脑用到我们的顺序中,我们须要一个工场,接收一个参数,然后它就可以返回响应的工具:

package designpattern.staticfactorymethod;
public class CalculateFactory {
     public static Calculate create(String operate) {
           switch (operate) {
           case " ":
                return new Plus();
           case "-":
                return new Minus();
           case "*":
                return new Multiply();
           case "/":
                return new Divide();
           }
           return null;
     }
}
前面的类都新增了一个默许的组织要领,就是为了这里用,我也思索过,可不克不及够用一致的带参数组织要领,但我看彷佛没有人这么写,一定有它的原理,这里写下本身深刻的明白,迎接交换、斧正: 工场的义务只是消费工具,加上参数就相当于和营业搅在一同,变得很不天真,本日你只想初始化汽车的品牌,来日诰日你又想初始化汽车的色彩,如许,你汽车类、工场类、挪用工场的类全要改,若是只是默许的组织要领的话,最少你的工场类是不消改的。   接下来看挪用的要领:
package designpattern.staticfactorymethod;
import java.util.Scanner;
public class Calculator4 {
     public static void main(String[] args) {
           Scanner scanner = new Scanner(System.in);
           System.out.println("请输入一个数字");
           double num1 = scanner.nextDouble();
           System.out.println("请输入一个运算符: 、-、*、/");
           String operator = scanner.next();// 不克不及用nextLine(),会把上一个回车给吸取
           System.out.println("请输入一个数字");
           double num2 = scanner.nextDouble();
           Calculate calculate = CalculateFactory.create(operator);
           calculate.num1 = num1;
           calculate.num2 = num2;
           System.out.println(calculate.calculate());
           scanner.close();
     }
}

 这回多态也进场了,经由过程多态,一致用父类接收建立的详细子类,当须要增添运算体式格局时,只须要修正工场类和详细的运算类,挪用的处所不消变,降低了模块间的耦合性,提高了体系的天真性。

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。