headfirst工厂方法

0. 序

初学Java,制造对象都是new ,针对实现编程。这种情况使实例化对象公开的进行,同时也造成耦合。那么可以使用工厂方法来解决。

//例子 在应用程序中需要实例化一只鸭子
Duck duck;//鸭子接口
if(是玩具鸭)
    duck= new 玩具鸭
if(是野鸭)
    duck=new 野鸭
if(是家养鸭)
    duck=new 家养鸭
    ...
 
 //可见针对实现编程的缺点 而且一旦发生变化,例如鸭子实现类的改变,那么就要去改动系统中涉及到这部分的代码。
 //实际上这部分 鸭子实例是变化的 而根据我们之前的原则,要取出变化的部分。并且 --开放闭合

即我们需要把实例化的代码从应用中抽离或者封装,使它们不会干扰其他部分。在内部只是保留一个接口即可(使用多态)

1. 工厂方法

简单点说,就是把创建对象的地方称为工厂,通过工厂来new一个对象提供给程序使用。这样**,就通过工厂来封装new对象的部分**。工厂来管理创建对象时的细节,无论他是玩具鸭子还是野鸭,交给工厂来处理,并最后返回一个Duck超类。如果以后我们需要增加鸭子类,只需要在工厂中做改变即可,不会涉及到引用鸭子类的部分。

//鸭子工厂
class DuckFactory{
	public	static Duck createDuck(String type){
			Duck duck=null;
			if(type=“玩具鸭”)
			duck=new 玩具鸭;
				....
			
			return duck;//工厂返回制造的对象
	}
//烤鸭子
class RoastDuck{
	DuckFactory factory;//工厂  组合的方式
	public RoastDuck(DuckFactory factory){
	this.factory=factory;
	}
	public Duck roast(String type){
		Duck duck=null;
		//之前的代码
		//if(type="玩具鸭")
		//	玩具鸭;
		
		//现在
		duck=factory.createDuck(type);//根据type 工厂制作一个鸭子
		...
	}
}
}
//注意:这是一个简单工厂

简单工厂方法在我看来是比较简单的,复杂也只是存在于工厂与抽象工厂。工厂模式中一个工厂只能生产一种产品,而抽象工厂可以生产多个。例如鸭子工厂还能生产饮料产品。

定义:工厂方法定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类。

结合书上的 披萨店 可知:一个工厂可能存在多个子类工厂,而这些子类工厂生产的产品是自己决定的。所以要把制造产品的方法递给子类工厂。

在这里插入图片描述

在这里,Creator与ConcreteCreator直接的实现 可以解耦。在使用产品时,产生产品只需要使用Creator的多态即可,不需要依赖ConcreteCreator

P134 P135处解释很好

原则:依赖倒置:要依赖抽象,不要依赖具体类。

解释一下:以披萨店为例,如果针对实现去编程,那么就把生产披萨的方法交给披萨店,那么后续如果该披萨店要修改披萨种类数量,就要去披萨店修改代码。那么这里,披萨店依赖具体的披萨类。披萨店是高层组件,依赖实现。 如果在披萨店的类里使用组合的方式加入工厂,它的披萨类定义成披萨接口(多态),把披萨交给工厂来生产,那么就可以把披萨店与披萨的变化分开。

所谓倒置:在之前是高层组件依赖低层,现在是低层依赖高层

倒置前

在这里插入图片描述

倒置后
在这里插入图片描述

几个方针帮助遵循此原则:

  • 变量不可用持有具体类的引用:如果使用new, 那不就是针对实现编程了?
  • 不要让类派生自具体类:要依赖抽象,使用多态
  • 不要覆盖基类中已经实现的方法:如果覆盖基类已实现的方法,那么这个基类就不是一个真正适合被继承的抽象。基类中已经实现的方法,应该由所有子类共享。
  1. 抽象工厂

    抽象工厂实际上就是一个工厂能够生产多个产品。这些产品的实现取决于子类工厂。

    //原料抽象工厂
    public interface PizzaIngredientFactory {
        Dough createDough();//面团
        Sauce createSauce();//酱汁
        Cheese createCheese();
        Veggies[] createVeggies();
        Pepperoni createPepperoni();
        Clams createClam();
    }
    //子类工厂
    //子类来决定抽象原料的实现
    public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
        @Override
        public Dough createDough() {
            return NY特色面团;
        }
    }
    

    实际上,抽象工厂的每个方法看起来是工厂方法。它的每个方法都是抽象的,由子类去覆盖这些方法。抽象工厂方法的任务是定义一个负责创建一组产品的接口,这个接口每个方法都负责创建一个具体的产品。由抽象工厂子类去实现具体做法。

这一章通读下来,我发现我之前所用到的工厂方法只是简单工厂方法… 这一部分的内容书上的例子比较多且通俗易懂,这里就不做搬运了…

小结

  • 简单工厂

    就在工厂类里实例化对象

    class SimplePizzaFactory{
        Pizza createPizza(type){
            Pizza pizza;
            if(type为奶酪)
                pizza=奶酪类型pizza;
            esle if
                ...
        }
    }
    
  • 工厂方法

    工厂定义一个实现产品的接口,由子类工厂去实现该接口 是一个继承的关系

    abstract class PizzaFactory{
        abstract Pizza createPizza(String type);//超类的接口
    }
    class NYPFactory extends PizzaFactory{
        Pizza createPizza(type){
            //生产出NY的pizza
        }
    }
    
  • 抽象工厂方法

    对比工厂方法,工厂方法只生产一种产品–pizza ; 抽象工厂方法生产多种不同的产品–酱料/面团/佐料/…

    //抽象工厂--原料
    public interface PizzaIngredientFactory {
      Dough createDough();//面团
        Sauce createSauce();//酱汁
        Cheese createCheese();
        Veggies[] createVeggies();
        Pepperoni createPepperoni();
        Clams createClam();
    }
    //子类工厂
    class NYPizzaIngredientFactory implements PizzaIngredientFactory{
        //重写上述抽象工厂的方法
    }
    //那么最后就可以在Pizza产生的过程中使用NYPizzaIngredientFactory来控制原料的使用与生产
    
发布了9 篇原创文章 · 获赞 4 · 访问量 4245

猜你喜欢

转载自blog.csdn.net/qq_42239081/article/details/104966014