工廠設計模式
簡介
工廠設計模式是最常見的設計模式之一,在工廠模式中,提供一種最佳的創建對象的方式,最大程度的實現代碼的解耦
-
什么是工廠模式? 通過一個工廠類創建類似功能的不同實現類的父類或接口,不用關注你所獲取的類是怎么實現的,只要通過工廠獲取到對象即可使用
-
工廠模式需要的三大模塊:
- 一個父類或者一個接口:定義該功能的方法、屬性
- 一個實現類或者子類:實現或者繼承上面的接口或者父類
- 工廠類:通過工廠類獲取實現類的父類或者接口(這里用到的多態)
-
優點:
- 擴展性高:當你想增加一個產品,只需要擴展工廠類,並增加一個產品即可
- 使用簡單:屏蔽了產品的具體實現,使用者只用關注產品的接口即可
- 高度解耦
-
缺點:
- 每次增加一個產品的時候都需要新增一個實現類,這樣下來類的數量不斷增加,增加了系統 復雜度
使用:在任何需要生成復雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是復雜對象適合使用工廠模式,而簡單對象,特別是只需要通過 new 就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的復雜度。
具體實現
例:輸入兩個數字和 + - * / 符號,實現加減乘除算法
初步實現:
public static void main(String[] args) {
boolean boo = true;
while (boo){
String next = "";
int a = 0;
int b = 0;
try {
System.out.println("請輸入第一個數字:");
Scanner scanner = new Scanner(System.in);
a = scanner.nextInt();
System.out.println("請輸入:+ - * / 四個符號");
Scanner scanner2 = new Scanner(System.in);
next = scanner2.next();
System.out.println("請輸入第二個數字:");
Scanner scanner1 = new Scanner(System.in);
b = scanner1.nextInt();
System.out.println("結果是:");
}catch (Exception e){
System.out.println("輸入有誤!!!");
e.printStackTrace();
}
switch (next){
case "+" :
System.out.println(a + b);
break;
case "-" :
System.out.println(a-b);
break;
case "*" :
System.out.println(a*b);
break;
case "/" :
if (b==0){
System.out.println("除數不能為0");
break;
}
System.out.println(a/b);
break;
default:
System.out.println("符號有誤");
}
System.out.println("是否關閉計算器?Y/N");
Scanner close = new Scanner(System.in);
String isClose = close.next();
if ("Y".equals(isClose)){
boo = false;
}
}
}
這樣寫完全可以實現了我們的加減乘除操作,但是卻不利於維護,比如當我們有其他地方也需要只用這個算法的時候我們就只能把switch代碼copy一份去使用,造成代碼冗余,而以后隨着業務的不斷增加可能還需要新增“開根”、“平方”等操作,如果我們在多個地方都這樣寫,可想而知我們需要改多少地方
那么有人會說,直接把switch代碼封裝起來,在其他地方調用就行了,無論需要怎么改我們只用修改這塊代碼即可。這樣我們的代碼就非常容易維護了
初步改造:
public static void main(String[] args) {
boolean boo = true;
while (boo){
String next = "";
int a = 0;
int b = 0;
try {
System.out.println("請輸入第一個數字:");
Scanner scanner = new Scanner(System.in);
a = scanner.nextInt();
System.out.println("請輸入:+ - * / 四個符號");
Scanner scanner2 = new Scanner(System.in);
next = scanner2.next();
System.out.println("請輸入第二個數字:");
Scanner scanner1 = new Scanner(System.in);
b = scanner1.nextInt();
System.out.println("結果是:");
}catch (Exception e){
System.out.println("輸入有誤!!!");
e.printStackTrace();
}
getResult(next, a, b);
System.out.println("是否關閉計算器?Y/N");
Scanner close = new Scanner(System.in);
String isClose = close.next();
if ("Y".equals(isClose)){
boo = false;
}
}
}
private static void getResult(String next, int a, int b) {
switch (next){
case "+" :
System.out.println(a + b);
break;
case "-" :
System.out.println(a-b);
break;
case "*" :
System.out.println(a*b);
break;
case "/" :
if (b==0){
System.out.println("除數不能為0");
break;
}
System.out.println(a/b);
break;
default:
System.out.println("符號有誤");
}
}
經過這次的改造,我們的代碼看着似乎已經非常棒了,可以很方便的修改算法,而且無論怎么改動我們只需要修改getResult方法即可
問題:所有算法全都暴露出來,當我們修改的時候不可避免的會觸碰到原來好的代碼,那么我們怎么樣才能做到各個功能,不同算法之間完全獨立呢?
解決:這個時候我們就需要用到工廠了
工廠模式下的加減乘除:
算法接口
public interface Algorithm {
public int getResult(int a,int b);
}
實現算法接口,不同的算法
public class Add implements Algorithm {
@Override
public int getResult(int a,int b) {
int sum = a + b;
return sum;
}
}
public class Sub implements Algorithm {
@Override
public int getResult(int a, int b) {
int sub = a - b;
return sub;
}
}
public class Mul implements Algorithm {
@Override
public int getResult(int a,int b) {
return a*b;
}
}
public class Division implements Algorithm {
@Override
public int getResult(int a,int b) {
if (b == 0){
throw new RuntimeException("除數不能為0");
}
return a/b;
}
}
這樣加減乘除的算法已經實現。那么我們在使用的時候需要創建不同的算法對象,等於在使用的時候還是暴露的直接的類,那么我們的定義的接口在這里只是起到了一個規范的作用,那么我們怎么才能不關注具體實現呢?或者說我們怎么才最大化的解耦
解決:使用面向接口編程
工廠類:通過工廠獲取不同算法的實現(這里用到了多態)
public class ComputeFactory {
public static Algorithm getAlgorithm(String symbol){
switch (symbol){
case "+":
return new Add();
case "-":
return new Sub();
case "*":
return new Mul();
case "/":
return new Division();
default:
throw new RuntimeException("符號有誤!!!");
}
}
}
現在我們可以直接從這里獲取算法,我們只關注接口就行了,不用關注下面的算法怎么實現的,這樣我們就最大程度的實現了功能的解耦
現在再看一下我們的最終的代碼,工廠類、接口、實現類,這就是一個完整的工廠模式,接下來我們來使用的時候就非常方便了
public static void main(String[] args) {
boolean boo = true;
while (boo){
System.out.println("請輸入第一個數字:");
Scanner scannerA = new Scanner(System.in);
int a = scannerA.nextInt();
System.out.println("請輸入:+ - * / 四個符號");
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
System.out.println("請輸入第二個數字:");
Scanner scannerB = new Scanner(System.in);
int b = scannerB.nextInt();
System.out.println("結果是:");
Algorithm algorithm = ComputeFactory.getAlgorithm(next);
int result = algorithm.getResult(a,b);
System.out.println(result);
System.out.println("是否關閉計算器?Y/N");
Scanner close = new Scanner(System.in);
String isClose = close.next();
if ("Y".equals(isClose)){
boo = false;
}
}
這樣我們在以后如果想再添加一個算法,或者修改一個算法的時候只用新增一個獨立的類或者就該某一個類的算法就行了,完全不存在影響其他算法的情況