简单工厂模式、工厂方法模式、抽象工厂模式
1.简单工厂模式
1.1 原始计算器
一个最简单的计算器类。
package factory.simplenessfactory.Simpleness_two;
import java.util.Scanner;
/**
* @ClassName CalculatorOne
* @Description 计算器原始版本
* @Author 萌白
* @Date 2019/7/15 11:00
* @Version 1.0
*/
public class CalculatorOne {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入参数:");
double num1 = scanner.nextDouble();
System.out.println("请输入运算方式:");
String s = scanner.next();
System.out.println("请输入参数:");
double num2 = scanner.nextDouble();
Double d = null;
switch (s) {
case "+":
d = num1 + num2;
break;
case "-":
d = num1 - num2;
break;
case "*":
d = num1 * num2;
break;
case "/":
d = num1 * num2;
break;
default:
System.out.println("此功能待扩展");
break;
}
System.out.println(d);
}
}
在这个类中计算器的基本功能已经实现,但是该程序不易维护,不易扩展,不易复用。所以该代码的质量极差。所以这样的代码是会被人给唾弃的。所以我们如何写一个容易维护,容易扩展,又容易复用呢?
1.2 面向对象的计算器
面向对象通过封装、继承、多态把程序的耦合度降低,如上面在其他地方使用的时候就得再次写一次代码,这就是代码的耦合度太高所致,可以使用设计模式使得程序更加的灵活。
我们只需要业务逻辑将其抽取到一个单独类即可。下面这个类,在你想使用它的时候,你只需要进行实例化该对象,然后调用该方法即可使用。这个就可以达到代码的复用性
这里是面向对象的封装。
/**
* @ClassName CalculatorTwo
* @Description 计算器面向对象版本
* @Author 萌白
* @Date 2019/7/15 11:28
* @Version 2.0
*/
class Calculator {
public static Double Calculator(double num1, double num2, String s) {
Double d = null;
switch (s) {
case "+":
d = num1 + num2;
break;
case "-":
d = num1 - num2;
break;
case "*":
d = num1 * num2;
break;
case "/":
d = num1 * num2;
break;
default:
System.out.println("此功能待扩展");
break;
}
return d;
}
}
再来一个客户端类
/**
* @ClassName CalculatorTwo
* @Description 计算器面向对象版本
* @Author 萌白
* @Date 2019/7/15 11:28
* @Version 2.0
*/
public class CalculatorTwo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入参数:");
double num1 = scanner.nextDouble();
System.out.println("请输入运算方式:");
String s = scanner.next();
System.out.println("请输入参数:");
double num2 = scanner.nextDouble();
Double calculator = Calculator.Calculator(num1, num2, s);
System.out.println(calculator);
}
}
在这个类中,也存在问题,那就是紧耦合,虽然我们已经将业务和客户端进行了分离,但是如果我们需要在添加一个开根原酸,我们就需要在Operation类中的switch中添加分支,虽然这种方式是可行的,但是需要改动运算类,所以,有可能导致把加法改成减法,这样问题就大发了^ _ ^,所以我们应该将所有的运算进行分离。
首先我们定义一个抽象类。
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName Operation
* @Description 抽象类
* @Author 萌白
* @Date 2019/7/15 14:33
* @Version 3.0
*/
public abstract class Operation {
private Double num1;
private Double num2;
//抽象方法,继承该类必须实现,功能:返回运算结果。
public abstract Double getResult();
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;
}
}
实现类,加减乘除类
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName OperationSum
* @Description 加法运算
* @Author 萌白
* @Date 2019/7/15 14:36
* @Version 3.0
*/
public class OperationSum extends Operation {
@Override
public Double getResult() {
return getNum1() + getNum2();
}
}
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName OperationSub
* @Description 减法类
* @Author 萌白
* @Date 2019/7/15 14:36
* @Version 3.0
*/
public class OperationSub extends Operation {
@Override
public Double getResult() {
return getNum1() + getNum2();
}
}
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName OperationMul
* @Description 乘法类
* @Author 萌白
* @Date 2019/7/15 14:37
* @Version 3.0
*/
public class OperationMul extends Operation {
@Override
public Double getResult() {
return getNum1() + getNum2();
}
}
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName OperationMul
* @Description 乘法类
* @Author 萌白
* @Date 2019/7/15 14:37
* @Version 3.0
*/
public class OperationMul extends Operation {
@Override
public Double getResult() {
return getNum1() + getNum2();
}
}
工厂类
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName OperationFactory
* @Description 简单工厂类
* @Author 萌白
* @Date 2019/7/15 14:39
* @Version 3.0
*/
public class OperationFactory {
public static Operation createOperation(String operate) {
Operation ope = null;
switch (operate) {
case "+":
ope = new OperationSum();
break;
case "-":
ope = new OperationSub();
break;
case "*":
ope = new OperationMul();
break;
case "/":
ope = new OperationDiv();
break;
default:
System.out.println("功能有待扩展...");
break;
}
return ope;
}
}
客户端
package factory.simplenessfactory.Simpleness_two.SimplenessFactory;
/**
* @ClassName OperationClient
* @Description 客户端类
* @Author 萌白
* @Date 2019/7/15 14:43
* @Version 3.0
*/
public class OperationClient {
public static void main(String[] args) {
Operation operation = OperationFactory.createOperation("+");
operation.setNum1(11d);
operation.setNum2(12d);
Double result = operation.getResult();
System.out.println(result);
}
}
这就是一整套的简单工厂模式了,这个模式的好处在,在添加新的功能的时候,你只需要在添加一个新的类,实现抽象类,然后实现其中的方法,在工厂类中添加对应的分支,这样在功能添加的时候又不会改动其他算法类的代码。
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,更具客户端的选择条件动态实例化相关的类,对于客户端来
说,去除了与具体产品的依赖。
简单工厂模式结束,华丽分割线
工厂方法模式
简单工厂模式和工厂方法模式的区别在于工厂类的不同,简单工厂模式中,工厂类在添加算法类的时候,需要添加case分支,这样违背了开放封闭原则,而在工厂方法模式中,每一个算法类多有单一的工厂类,这个是单一职责原则。
- 我们定义工厂方法创建的对象的接口或者抽象类
- 具体的产品实现对象的接口或者抽象类
- 定义一个工厂接口或抽象类,其中包含返回对象的方法。
- 实现工厂接口,实现方法。
package factory.methodfactory.mode_one;
/**
* @ClassName Car
* @Description 抽象类
* @Author 萌白
* @Date 2019/7/12 10:50
* @Version 1.0
*/
public abstract class Car {
//车的名字
public String name;
//车的颜色
public String color;
//生产车的抽象方法
public abstract void car();
}
车的具体实现类
package factory.methodfactory.mode_one;
/**
* @ClassName Lamborghini
* @Description 制造兰博基尼具体实现类
* @Author 萌白
* @Date 2019/7/12 10:52
* @Version 1.0
*/
public class Lamborghini extends Car {
@Override
public void car() {
System.out.println("车的名字叫做 >>> " + name + "颜色是 >>> " + color);
}
}
package factory.methodfactory.mode_one;
/**
* @ClassName Maserati
* @Description 制造玛莎拉蒂的具体实现类
* @Author 萌白
* @Date 2019/7/12 10:53
* @Version 1.0
*/
public class Maserati extends Car {
@Override
public void car() {
System.out.println("车的名字叫做 >>> " + name + "颜色是 >>> " + color);
}
}
定义一个工厂接口,所有的工厂类来实现它。
package factory.methodfactory.mode_one;
/**
* @ClassName CreateCarFactory
* @Description 工厂类的接口,所有的工厂类多实现它
* @Author 萌白
* @Date 2019/7/12 10:54
* @Version 1.0
*/
public interface CreateCarFactory {
public Car createCar();
}
工厂类实现类
package factory.methodfactory.mode_one;
/**
* @ClassName CreateLamborghiniFactory
* @Description 生产兰博基尼的工厂类
* @Author 萌白
* @Date 2019/7/12 10:55
* @Version 1.0
*/
public class CreateLamborghiniFactory implements CreateCarFactory {
@Override
public Car createCar() {
return new Lamborghini();
}
}
package factory.methodfactory.mode_one;
/**
* @ClassName CreateMaseratiFactory
* @Description 生成玛莎拉蒂的工厂类
* @Author 肖杰斌
* @Date 2019/7/12 10:56
* @Version 1.0
*/
public class CreateMaseratiFactory implements CreateCarFactory {
@Override
public Car createCar() {
return new Maserati();
}
}
测试类
package factory.methodfactory.mode_one;
/**
* @ClassName CarTest
* @Description 类的描述
* @Author 萌白
* @Date 2019/7/12 10:57
* @Version 1.0
*/
public class CarTest {
public static void main(String[] args) {
CreateMaseratiFactory createMaseratiFactory = new CreateMaseratiFactory();
Car car = createMaseratiFactory.createCar();
car.color="绿色";
car.name="玛莎拉蒂";
car.car();
}
}
工厂方法模式结束,华丽分割线
抽象工厂模式
抽象工厂模式的优点
好处就是易于叫换产品,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就是的改变一个应用的具体工厂变得非常容易,他只需要改变具体工厂即可使用不同的产品配置。他让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现锋利,不会出现在客户端代码中。
抽象工厂模式的创建:
1. 定义抽象产品(Apple Banana)
2. 对抽象产品进行实现
3. 定义抽象工厂接口,其中包含所有产品创建的抽象方法。(FruitFactory)
4. 具体的工厂,创建具有特定实现的产品对象。
1.定义抽象产品:
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName Apple
* @Description 定义苹果
* @Author 肖杰斌
* @Date 2019/7/15 15:55
* @Version 1.0
*/
public interface Apple {
public void apple();
}
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName Banana
* @Description 接口的描述
* @Author 肖杰斌
* @Date 2019/7/15 15:56
* @Version 1.0
*/
public interface Banana {
public void banana();
}
2.定义抽象产品实现
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName NorthApple
* @Description 苹果实现类
* @Author 萌白
* @Date 2019/7/15 15:46
* @Version 1.0
*/
public class NorthApple implements Apple {
@Override
public void apple() {
System.out.println("这是北方的苹果...");
}
}
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName SouthApple
* @Description 苹果实现类
* @Author 萌白
* @Date 2019/7/15 15:46
* @Version 1.0
*/
public class SouthApple implements Apple {
@Override
public void apple() {
System.out.println("这是南方的苹果...");
}
}
香蕉实现类
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName DomesticBanana
* @Description 香蕉的实现类
* @Author 萌白
* @Date 2019/7/15 15:48
* @Version 1.0
*/
public class DomesticBanana implements Banana {
@Override
public void banana() {
System.out.println("这是国内的香蕉...");
}
}
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName ImportedBanana
* @Description 香蕉的实现类
* @Author 萌白
* @Date 2019/7/15 15:48
* @Version 1.0
*/
public class ImportedBanana implements Banana {
@Override
public void banana() {
System.out.println("进口的香蕉...");
}
}
3.定义抽象工厂接口
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName FruitFactory
* @Description 创建水果的工厂
* @Author 萌白
* @Date 2019/7/15 15:45
* @Version 1.0
*/
public interface FruitFactory {
public Banana createBanana();
public Apple createApple();
}
4.具体的工厂
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName CreateNorthFactory
* @Description 类的描述
* @Author 萌白
* @Date 2019/7/15 16:03
* @Version 1.0
*/
public class CreateNorthFactory implements FruitFactory {
@Override
public Banana createBanana() {
return new DomesticBanana();
}
@Override
public Apple createApple() {
return new NorthApple();
}
}
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName CreateSouthFactory
* @Description 类的描述
* @Author 萌白
* @Date 2019/7/15 16:00
* @Version 1.0
*/
public class CreateSouthFactory implements FruitFactory {
@Override
public Banana createBanana() {
return new ImportedBanana();
}
@Override
public Apple createApple() {
return new SouthApple();
}
}
5.客户端
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName FruitClient
* @Description 类的描述
* @Author 萌白
* @Date 2019/7/15 16:05
* @Version 1.0
*/
public class FruitClient {
public static void main(String[] args) {
CreateNorthFactory createNorthFactory = new CreateNorthFactory();
Apple appleFactory = createNorthFactory.createApple();
Banana bananaFactory = createNorthFactory.createBanana();
appleFactory.apple();
bananaFactory.banana();
}
}
我们还可以使用简单工厂来对抽象工厂进行改进。可以去除FruitFactory、CreateNorthFactory、CreateSouthFactory三大工厂。
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName CreateFruit
* @Description 简单工厂
* @Author 萌白
* @Date 2019/7/15 16:49
* @Version 1.0
*/
public class CreateFruit {
private static final String FRUIT = "north";
// private static final String fruit="south";
public static Apple createApple() {
Apple result = null;
switch (FRUIT) {
case "north":
result = new NorthApple();
break;
case "south":
result = new SouthApple();
}
return result;
}
public static Banana createBanana() {
Banana result = null;
switch (FRUIT) {
case "north":
result = new ImportedBanana();
break;
case "south":
result = new DomesticBanana();
break;
}
return result;
}
}
客户端
package factory.abstractfactory.abstractfactory_two;
/**
* @ClassName FruitClient
* @Description 类的描述
* @Author 萌白
* @Date 2019/7/15 16:05
* @Version 1.0
*/
public class FruitClient {
public static void main(String[] args) {
//使用简单工厂优化
Apple apple = CreateFruit.createApple();
apple.apple();
Banana banana = CreateFruit.createBanana();
banana.banana();
}
}
拓展:在抽象工厂类中,还可以使用反射+配置文件的方式进行来实现。