工厂模式之所以叫工厂,就是因为工厂里面会new产品
工厂模式的三种实现方法
1 简单工厂模式
1.1 不好的实现方法(无工厂)
1.1.1角色组成
- 抽象产品角色,为具体产品提供接口
- 具体产品角色,继承抽象产品的接口并覆写方法
- 使用类,分别创建具体产品角色,调用它的方法
1.1.2 具体实现
开餐厅,首先定义什么是食物
//1抽象产品角色
package com.Food;
public interface Food {
public void cook();
}
准备几个食物的做法
//2具体产品角色
package com.menu;
import com.Food.Food;
public class Meat implements Food{
@Override
public void cook() { //覆写继承来的cook方法
system.out.println("炒一盘小炒肉!")﹔
}
}
public class Fish implements Food{
@Override
public void cook() { //覆写继承来的cook方法
system.out.println("炒一盘鱼香肉丝!")﹔
}
}
public class Duck implements Food{
@Override
public void cook() { //覆写继承来的cook方法
system.out.println("炒一盘鸭鸭!")﹔
}
}
客人到店后开始点餐。
//3使用类
package com;
import com.Food.Food;
import com.menu.Duck;
import com.menu.Meat;
import com.menu.Fish;
public class Customer{
public static void main(String[] args) {
Food food= new Meat();//new其中一个具体产品
food.cook();//调用具体覆写的cook方法
Food food2= new Duck();
Food2.cook();
}
}
1.1.3 方法解读
- 定义一个接口Food为所有食物总类,所有事物都内有一个cook方法,3种食物继承了总食物接口并覆写具体的cook方法
- 客人到店,创建(new)3种食物class中的一种,并调用它的cook方法(相当于客人直接炒菜)
1.1.4 缺点
三个实现类和接口紧密的绑定到了一起,代码耦合出现严重问题,不利于以后的维护
1.2 进化版实现方法【简单模式里面最经典的】
1.2.1 角色组成
- 抽象产品角色:由接口或者抽象类来实现,为3提供接口。
- 具体产品角色:由一个具体类实现,等着1工厂类来创建的我。
- 工厂类角色:往往由一个具体类实现,创建2具体产品角色。【新增】
- 使用类:创建工厂类,由工厂类创建某个具体产品,再调用具体产品的具体方法
1.2.2 具体实现
//2抽象产品角色
public interface Car{
public void drive();
}
//3具体产品角色
public class Benz implements Car{
public void drive() {
System.out.println("Driving Benz ");
}
}
public class Bmw implements Car{
public void drive() {
System.out.println("Driving Bmw ");
}
}
public class AD implements Car{
public void drive() {
System.out.println("Driving AD ");
}
}
//1工厂类角色 ——相当于简单工厂模式上菜增加服务员,告诉后厨客人要什么菜
public class Driver{
//工厂方法
//注意 返回类型为抽象产品角色
public static Car driverCar(String s) throws Exception {
//判断逻辑,返回具体的产品角色给Client
if(s.equalsIgnoreCase("Benz")) return new Benz();
else if(s.equalsIgnoreCase("Bmw")) return new Bmw();
else if(s.equalsIgnoreCase("AD")) return new AD();
else throw new Exception();
}
}
//老板,是使用类
public class Magnate{
public static void main(String[] args) {
Try {
//告诉司机(工厂类)我今天坐奔驰
Car car = Driver.driverCar("benz");
//下命令:开车
//这里不同的车,但是写法一样,调用他们覆写的drive方法
car.drive();
}catch(){
…
}
}
1.2.3 方法解读
- 首先定义一个接口car,内有一个drive方法(1抽象产品角色)
- 定义几种不同类型的车,他们都继承接口并覆写drive方法(2具体产品角色)
- 定义一个司机,他通过字符串接收老板的信号,知道老板今天想开什么车,如果是想开奔驰则new一台奔驰给老板(3工厂类角色)
- 老板创建一个Car类的变量car,通过上一步创建的司机的方法得到返回的new benz(),现在老板创建的变量car就对应了一个new出来的新车,再调用该车的drive方法
1.2.4 优缺点
优点:客户端免除了直接创建产品对象的责任,而仅仅负责"消费"产品
缺点:
- 每增加一辆车,都要在工厂类中增加相应的逻辑
- 只有一个工厂类
- 不支持不同产品需要不同参数,而且传错参数的容错率不高
1.3 多方法静态工厂(增加参数)
该方法为不同产品提供不同的生产方法,使用时需要哪种产品就调用该种产品的方法,使用方便、容错率高。
该方法仅是用于改进1.2的第三个缺点。
具体实现如下:
//抽象类
package com.hdnav;
public interface Food{
public void cook();
}
//实现类
package com.hdnav;
public class Meat implements Food{
String param;
public Meat(String param) {
this.param = param;
}
@Override
public void cook() {
system.out.println("来盘小炒肉!"+param);
}
}
public class Fish implements Food{
@Override
public void cook() { //覆写继承来的cook方法
system.out.println("炒一盘鱼香肉丝!")﹔
}
}
public class Duck implements Food{
@Override
public void cook() { //覆写继承来的cook方法
system.out.println("炒一盘鸭鸭")﹔
}
}
//工厂类
package com.hdnav;
public class CookFactory {
public static Food createMeet(String param) {
return new Meet(param);
}
public static Food createFish() {
return new Fish();
}
pubiic static Food createDuck() {
return new Duck();
}
}
//使用类
package com.hdnav;
public class Test {
public static void main(string[ ] args) {
Food meetCooker = CookFactory.createMeet("三分熟")﹔
meatCooker.cook();
Food duckCooker = CookFactory.createDuck();
duckCooker.cook();
Food fishCooker = CookFactory.createFish();
fishCooker.cook();
}
}
分析:
相当于静态的改写某一个方法,增加了一个参数
2 工厂方法模式
2.1 角色组成
- 抽象产品角色:由抽象类或者接口来实现,为具体产品提供接口。
- 具体产品角色:由具体类实现,继承抽象产品的接口,实现具体产品独特的使用方法
- 抽象工厂角色:由抽象类或者接口来实现,为具体工厂提供接口。
- 具体工厂角色:由具体的类来实现,生产2具体产品。【新增】——相当于给原来的司机增加小弟,不是一个司机创造所有车而是不同司机创造不同的车(原来的司机成为一个抽象大工厂,小弟成为具体小工厂)
- 使用类:创建具体工厂,由该具体工厂创建对应的具体产品,调用具体产品的使用方法
2.2 具体实现
//1抽象产品角色
public interface Car{
public void drive();
}
//2具体产品角色
public class Benz implements Car{
public void drive() {
System.out.println("Driving Benz ");
}
}
public class Bmw implements Car{
public void drive() {
System.out.println("Driving Bmw ");
}
}
public class AD implements Car{
public void drive() {
System.out.println("Driving AD ");
}
}
//3抽象工厂角色
public interface Driver{
public Car driverCar();
}
//4具体工厂角色
public class BenzDriver implements Driver{
public Car driverCar(){
return new Benz();
}
}
public class BmwDriver implements Driver{
public Car driverCar() {
return new Bmw();
}
}
public class ADDriver implements Driver{
public Car driverCar() {
return new AD();
}
}
//5 使用类
public class Magnate
{
public static void main(String[] args)
{
Try {
Driver driver = new BenzDriver();
Car car = driver.driverCar();
car.drive();
} catch(Exception e)
{ … }
}
}
2.3 解读
- 定义抽象产品角色Car类,定义一个方法drive。(每个车都有被开的方法)
- 定义具体产品角色Benz/BMW等,覆写drive方法。(具体描述每个车是怎么开的)
- 定义抽象工厂角色Driver类,定义一个Car类的drivecar方法(会造各种车的司机大类)
- 定义具体工厂角色,覆写Car类的drivecar方法(即new一个Benz并返回)(具体创造某个车的小司机)
- 使用类,先创造一个小司机(具体工厂)(new一个奔驰司机,用一个Driver类的变量driver来接),再让刚刚创造的小司机(具体工厂)造车(具体产品)(调用小司机的driverCar方法,new一台车),再开这个车(调用车的drive方法)
3 抽象工厂模式
3.1 与工厂方法的区别
原来工厂方法要增加新产品(增加飞机而不是新类别的车)的话,就要重新增加一个抽象工厂,然后再增加具体工厂,类别多了抽象工厂数量会大增。而抽象工厂模式把不同产品放到一个抽象工厂里面,比如A厂=A车+A飞机,而不是A车厂=A车,A机场=A机。
工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类
而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
3.2 角色组成
与工厂方法一样,只是抽象工厂的内部多了东西。
- 抽象工厂角色:为具体工厂提供接口,提供所有抽象产品。
- 具体工厂角色:由具体的类来实现,继承抽象工厂的接口。生产具体产品。
- 抽象产品角色:由抽象类或者接口来实现,等具体产品继承。
- 具体产品角色:具体的类来实现,继承抽象产品接口。
- 使用类:创建具体工厂,由该具体工厂创建对应的具体产品,调用具体产品的使用方法
3.3 具体实现
//抽象产品
package com.long88.ad.test;
interface Car {
public void getCar();
}
interface Plane{
public void getPlane();
}
interface Boat{
Public void getBoat();
}
//Car的具体产品
public class BMW implements Car{
@Override
public void getCar() {
System.out.printf("来一辆BMW!");
}
}
public class BYD implements Car {
@Override
public void getCar() {
System.out.printf("来一辆BYD!");
}
}
-----------------------------------
//Plane的具体产品
public class AirPlane implements Plane{
@Override
public void getPlane() {
System.out.printf("来一架客机!");
}
}
public class BattlePlane implements Plane{
@Override
public void getPlane() {
System.out.printf("来一架战斗机!");
}
}
-----------------------------------
//Boat的具体产品
public class ABoad implements Boat{
@Override
public void getBoat() {
System.out.printf("来一个A船!");-
}
}
public class Aboad implements Boat{
@Override
public void getBoat() {
System.out.printf("来一架B船!");
}
}
//抽象工厂
interface Factory{
public Car getCarByFactory();
public Plane getPlaneByFactory();
public Boat getBoatByFactory();
}
// 具体工厂类1
class FactoryOne implements Factory{//车2+飞机1
@Override
public Car getCarByFactory() {
return new BYD();
}
@Override
public Plane getPlaneByFactory() {
return new AirPlane();
}
}
-----------------------------------
// 具体工厂类2
class FactoryTwo implements Factory{//车2+船1
@Override
public Car getCarByFactory() {
return new BYD();
}
@Override
public Plane getBoatByFactory() {
return new ABoat ();
}
}
//使用类
public class TestFactory {
public static void main(String[] args) {
Car byd = new FactoryTwo().getCarByFactory();
byd.getCar();
Plane airPlane = new FactoryOne().getPlaneByFactory();
airPlane.getPlane();
}
}
3.4 方法解读
原来工厂造的东西都是不同类别的车,而现在抽象工厂造的是不仅是车,而是车+飞机+船,也就是可以造不同抽象产品,而具体工厂选择抽象工厂提供的产品进行制造,比如A厂选了车+飞机,那他可以制造某种(而非各种)车和某种飞机。
抽象产品=车,飞机,船,具体产品=宝马/奔驰/比亚迪车,战斗机/客机等等。
使用类首先创建一个新的2号抽象工厂,并调用他的生产车函数创建一辆BYD,并用byd接住,再调用byd车的驾驶方法。
4 参考资料
https://blog.csdn.net/qq564425/article/details/81082242
https://www.cnblogs.com/long88-club/p/11055555.html
https://www.jb51.net/article/85699.htm
https://www.cnblogs.com/carryjack/p/7709861.html