文章目录
简单工厂
简单工厂具体来说不算一种模式,
而是一种设计思想————将业务逻辑和界面逻辑分离,即服务端和客户端分离
在不需要客户端进行修改,在服务端修改增加产品类即可。
具体的做法:
1.创建工厂类作为父类,产品类作为工厂类子类,具体产品类作为产品类子类
2.工厂类根据客户端选择参数的不同,建立创建产品函数返回产品对象,产品类写出方法,具体产品类作为具体实现
服务端代码:
服务端
public class Factory{
// 工厂制作**相应的产品对象**
public FoodProduct createProduct(int choose){
FoodProduct food = null;
switch (choose){
case 1:
food = new Hamburger();
break;
case 2:
food = new Rice();
break;
default:
food = null;
break;
}
return food;
}
}
// 食物产品确定需要的动作
public class FoodProduct extends Factory{
private double price;
public double getPrice() {return price;}
public void setPrice(double price) {
this.price = price;
}
public void showInfo(){};
}
// 具体的汉堡产品实现具体的操作,比如实现价格显示,和价格初始化
public class Hamburger extends FoodProduct{
// 价格初始化
public Hamburger(){
this.setPrice(18.0);
}
// 具体实现了展现信息
@Override
public void showInfo(){
System.out.println("汉堡的价格为" + this.getPrice());
}
}
//具体的米饭产品实现
public class Rice extends FoodProduct{
// 价格初始化
public Rice(){
this.setPrice(38.0);
}
// 具体实现了展现信息
@Override
public void showInfo(){
System.out.println("米饭的价格为" + this.getPrice());
}
}
客户端的代码:
public class Main{
public static void main(String[] args){
Factory hamburger = new Factory();
FoodProduct food;
//客户端输入具体的参数,就能获得相应的产品对象
food = hamburger.createProduct(1);
}
}
UML图如下:
优点:
1.实现了对象创建和使用的分离(即业务逻辑和界面逻辑分离)。
2.客户端无需知道所创建的具体产品类的类名,只需知道具体产品类所对应的参数即可。
3.通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点我就不说了,因为很明显,这是仅仅是一个经常要用到的思想,但是真正的工程不可能这么简单的,缺点很多也很致命,这个算不上设计模式。
工厂方法模式
工厂方法和简单工厂最大的区别就是在于制造了将原本的工厂抽象成工厂接口,具体的对象创建延迟到下面具体的工厂子类来实现,使增加新的工厂产品时不用修改代码,只需增加类即可。
工厂模式具体做法:
1,定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。
2…工厂子类根据客户端选择参数的不同,建立创建产品函数返回产品对象,产品类写出方法,具体产品类作为具体实现。
服务端
// 抽象工厂接口
public interface Factory{
public FoodProduct createProducts();
}
// 两个具体的生产产品工厂
public class HamburgerProductFactory implements Factory {
// 工厂制作**相应的产品对象**
public FoodProduct createProducts(){
return new Hamburger();
}
}
public class RiceProductFactory implements Factory {
// 工厂制作**相应的产品对象**
public FoodProduct createProducts(){
return new Rice();
}
}
// 食物产品确定需要的动作
public class FoodProduct{
private double price;
public double getPrice() {return price;}
public void setPrice(double price) {
this.price = price;
}
public void showInfo(){};
}
// 具体的汉堡产品实现具体的操作,比如实现价格显示,和价格初始化
public class Hamburger extends FoodProduct{
// 价格初始化
public Hamburger(){
this.setPrice(18.0);
}
// 具体实现了展现信息
@Override
public void showInfo(){
System.out.println("香辣汉堡的价格为" + this.getPrice());
}
}
//具体的米饭产品实现
public class Rice extends FoodProduct{
// 价格初始化
public Rice(){
this.setPrice(38.0);
}
// 具体实现了展现信息
@Override
public void showInfo(){
System.out.println("米饭的价格为" + this.getPrice());
}
}
客户端的代码:
public class Main{
public static void main(String[] args){
// 客户端当要创建汉堡时,去用多态实例化一个汉堡工厂对象
Factory hamburger = new HamburgerProductFactory();
//客户端选择对应的创建函数,能创建相应的产品对象
FoodProduct food = hamburger.createProducts();
}
}
UML图如下:
简单工厂 VS 工厂方法
简单工厂的好处就是实现对象创建与使用的分离,而这点工厂方法也通过它的做法做到了
所以简而言之,工厂方法是简单工厂的升级版。
但是简单工厂的问题,工厂方法有全部避免了吗??
1.首先简单工厂违背的开放——封闭原则,即对扩展开放,对修改封闭
——工厂方法通过创建了工厂接口,将创建对象实例化,延迟到了子类,当需要增加新的产品时,只需增加类即可,不需要修改原先的代码,满足了开放–封闭。
——但是同时工厂方法也暴露了一个很重要的问题,就是简单工厂的逻辑判断从工厂类转移到了客户端,当我需要米饭类产品时,就需要修改客户端了!!(反射可以优化)
2.同时工厂方法还有一个缺点:每次新增产品,产品类都需要创建对应工厂类,虽然满足了开放–封闭原则,但是增加了系统的开销。
同时为了引出第三个抽象工厂,我们需要知道产品等级结构和产品族的概念:
产品等级结构:产品等级结构即产品的继承结构
产品族:同一个工厂生产的,位于不同产品等级结构中的一组产品
这张图很好的解释了产品族和产品等级结构,
例如上面代码的food作为一个产品,那么构成它的汉堡,米饭等等即为它的产品族,
而香辣汉堡,鸡肉汉堡,牛肉汉堡这些相似的产品则互组成产品等级结构,
作为子类继承父类汉堡
抽象工厂与工厂方法和简单工厂有一个很大的不同就是:多了产品等级结构,更加的复杂,也更符合现实的生活真实情况。
抽象工厂
理论抽象工厂UML图
之前写好过一个抽象工厂的,代码先po出来
// 抽象工厂接口
public interface FoodAbstractFactory {
Rice createRice(int num); //生产米饭
Hamburgers createHamburgers(int num); //生产汉堡
Noodles createNoodles(int num); // 生产面
}
具体工厂
// 具体工厂A香辣工厂
public class ConFoodFactory_Spicy implements FoodAbstractFactory {
/**
* 生产汉堡
* */
public Hamburgers createHamburgers(int num){
//香辣鸡腿堡
return new Hamburgers_Spicy(num);
}
/**
* 生产米饭
* */
public Rice createRice(int num) {
return new Rice_Spicy(num);
}
/**
* 生产面条
* */
public Noodles createNoodles(int num) {
//红烧牛肉面
return new Noodles_Spicy(num);
}
}
// 具体的
public class ConFoodFactory_Beef implements FoodAbstractFactory {
/*
* 生产汉堡
* */
public Hamburgers createHamburgers(int num){
//香辣鸡腿堡
return new Hamburgers_Beef(num);
}
/**
* 生产米饭
* */
public Rice createRice(int num) {
return new Rice_Beef(num);
}
/**
* 生产面条
* */
public Noodles createNoodles(int num) {
//红烧牛肉面
return new Noodles_Beef(num);
}
}
// 抽象物品信息类
public abstract class foodCommonInfo {
private int num; //数量
private double price; //价格
//计算餐品总价
public double totalPrice() {
//return this.num * this.price;
return num * price;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
// 多继承接口
public interface SingleFood {
void showOrderInfo();
void showMenuInfo();
}
public interface SingleFoodMenu extends SingleFood{
void showMenuInfo();
}
public interface SingleFoodOrder extends SingleFood {
void showOrderInfo();
}
各类产品类
// 汉堡产品类
public class HamburgersProduct extends foodCommonInfo implements SingleFood{
@Override
public void showOrderInfo() {
System.out.println("汉堡的价格——————————————" + this.getPrice());
}
@Override
public void showMenuInfo() {
System.out.println("汉堡类------------------------------------------------");
}
}
// 面条产品类
public class NoodlesProduct extends foodCommonInfo implements SingleFood{
@Override
public void showOrderInfo() {
System.out.println("面条的价格为————————" + this.getPrice());
}
@Override
public void showMenuInfo() {
System.out.println("面条类------------------------------------------------");
}
}
// 米饭产品类
public class RiceProduct extends foodCommonInfo implements SingleFood{
@Override
public void showOrderInfo() {
System.out.println("price");
}
@Override
public void showMenuInfo() {
System.out.println("米饭类------------------------------------------------");
}
}
具体个类产品类的实现
// 香辣汉堡的具体实现
public class Hamburgers_Spicy extends HamburgersProduct {
// 有参构造方法
public Hamburgers_Spicy(int num){
this.setNum(num);
this.setPrice(18.0);
}
public Hamburgers_Spicy(){
this.setPrice(18.0);
}
@Override
public void showOrderInfo(){
System.out.println("订购了香辣汉堡的价格为" + this.getPrice() + "元————" +
"数量为:" + this.getNum() + "个————" +
"总计:" + this.totalPrice() + "元");
}
@Override
public void showMenuInfo() {
System.out.println("1.香辣汉堡—————————————————————" + this.getPrice() + "元");
}
}
// 牛肉汉堡的具体实现
public class Hamburgers_Beef extends HamburgersProduct {
// 有参构造方法
public Hamburgers_Beef(int num){
this.setNum(num);
this.setPrice(28.0);
}
public Hamburgers_Beef(){
this.setPrice(28.0);
}
@Override
public void showOrderInfo(){
System.out.println("订购了牛肉汉堡的价格为" + this.getPrice() + "元————" +
"数量为:" + this.getNum() + "个————" +
"总计:" + this.totalPrice() + "元");
}
@Override
public void showMenuInfo() {
System.out.println("2.牛肉汉堡—————————————————————" + this.getPrice() + "元");
}
}
在这里我只列出汉堡具体类,米饭和面条大同小异,太长不列出来了。
点餐的客户代码:
// 客户client
public class Manangers {
//抽象工厂
private FoodAbstractFactory factory_con;
//构造方法将抽象工厂传入
public Manangers(FoodAbstractFactory factory_con) {
this.factory_con = factory_con;
}
/**
* 订购食物
*/
//汉堡
public double orderHamburgers(int num) {
//获得不同种类的汉堡 多态父类引用指向子类对象
HamburgersProduct hamburger = factory_con.createHamburgers(num);
//输出订购信息
hamburger.showOrderInfo();
//返回总价
return hamburger.totalPrice();
}
//面条
public double orderNoodles(int num) {
//获得面条
NoodlesProduct frenchFries = factory_con.createNoodles(num);
//输出订购信息
frenchFries.showOrderInfo();
//返回总价
return frenchFries.totalPrice();
}
//米饭
public double orderRices(int num) {
//获得不同种类的米饭
RiceProduct rice = factory_con.createRice(num);
//输出订购信息
rice.showOrderInfo();
//返回总价
return rice.totalPrice();
}
}
菜单展示代码
public class Menus implements SingleFoodMenu{
@Override
public void showMenuInfo() {
HamburgersProduct hamburgerskind = new HamburgersProduct();
HamburgersProduct hamburgers1 = new Hamburgers_Spicy();
HamburgersProduct hamburgers2 = new Hamburgers_Beef();
RiceProduct ricekind = new RiceProduct();
RiceProduct rice2 = new Rice_Beef();
RiceProduct rice1 = new Rice_Spicy();
NoodlesProduct noodleskind = new NoodlesProduct();
NoodlesProduct noodles2 = new Noodles_Beef();
NoodlesProduct noodles1 = new Noodles_Spicy();
System.out.println("-----------------------单品菜单------------------------");
hamburgerskind.showMenuInfo();
hamburgers1.showMenuInfo();
hamburgers2.showMenuInfo();
System.out.println("------------------------------------------------------");
noodleskind.showMenuInfo();
noodles1.showMenuInfo();
noodles2.showMenuInfo();
System.out.println("------------------------------------------------------");
ricekind.showMenuInfo();
rice1.showMenuInfo();
rice2.showMenuInfo();
System.out.println("------------------------------------------------------");
}
@Override
public void showOrderInfo() {}
}
客户端代码:
// 客户端
public class Main {
public static void main(String[] args) {
Menus menus = new Menus();
menus.showMenuInfo();
//建造订购者
// 建造香辣工厂
FoodAbstractFactory factory_spicy = new ConFoodFactory_Spicy();
Manangers order_spicy = new Manangers(factory_spicy);
// 订购商品
double price1 = order_spicy.orderNoodles(2);
double price2 = order_spicy.orderRices(3);
double price3 = order_spicy.orderHamburgers(1);
System.out.println( "餐品总价为" + (price1 + price2 + price3) + "元");
}
}
具体的结果展示:
抽象工厂模式更好的可以展示多种多样的产品,同时开放封闭原则还能得到很好的体现
UML图
PS:抽象工厂的具体工厂是生产的一个产品族还是产品等级结构是可以变的!!!!!
抽象工厂可以新增加产品族和产品等级结构,但是修改程度不同
①前提:具体工厂是抽取产品等级结构元素设计
例如我上述代码的香辣工厂,牛肉工厂
增加产品等级结构------符合开闭原则:
对于增加新的产品等级结构,抽象工厂模式很好地支持了开闭原则,只需要增加具体产品等级结构并对应增加一个新的具体工厂,对已有代码无须做任何修改。
增加新的产品族------不符合开闭原则:
增加新的产品族:对于增加新的产品族,例如我现在新增米线族,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了开闭原则。
②前提:具体工厂是抽取产品族元素设计
例如汉堡工厂,米饭工厂
增加产品族------符合开闭原则:
对于增加新的产品族,抽象工厂模式很好地支持了开闭原则,只需要增加具体产品等级结构并对应增加一个新的具体工厂,对已有代码无须做任何修改。
增加新的产品等级结构------不符合开闭原则:
增加新的产品等级结构:对于增加新的产品等级结构,例如我现在新增青椒族,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了开闭原则。
PS:这两个前提是我自己最近悟出来的,可能有对可能有错欢迎讨论,但是我觉着这样子变通,才可以让抽象工厂更加的灵活,不一定是网上说的一种情况。
最后由于客户端也需要的修改,我们可以用反射来优化。