简单工厂模式
例子:一个人想吃水果,就要自己new一个水果,多个人都要吃水果则这些人自己都要new一个水果。当这些人要的水果种类都不相同的时候都需要自己去new相应的水果,由于不同水果的采摘方法并不相同,也很容易会导致果园损坏。此时引入了园丁(工厂方法)的概念。
作用:将多个人所需要的水果都交给园丁进行采摘。
笨代码:
public void peterdo(){
Fruit fruit = new Apple();
Fruit.eat();
}
public void alexdo(){
Fruit fruit = new Banana();
Fruit.eat();
}
引入简单工厂方法后:
Public static StaticFactory(){
public static final int TYPE_APPLE = 1;
public static final int TYPE_ORANGE = 2;
public static final int TYPE_BANANA = 2;
public static Fruit getFruit(int type){
if(TYPE_APPLE == type){
return new Apple();
}else if(TYPE_ORANGE == type){
return new Orange(“name”,100);
}else if(TYPE_BANANA == type){
return new Banana();
}
}
}
public static doAction(){
public void peterdo(int type){
Fruit fruit = StaticFactory.getFruit(StaticFactory.TYPE_APPLE);
Fruit.eat();
}
}
这种方法需要关注类型的细节问题,以下改进后的工厂方法则不需要用户关注这个细节,可以比较直观的使用:
Public static StaticFactory(){
public static void Fruit getFruitApple(){
return new Apple();
}
public static void Fruit getFruitOrange(){
return new Orange(“name”,100);
}
public static void Fruit getFruitBanana(){
return new Banana();
}
}
public static doAction(){
public void peterdo(int type){
Fruit fruit = StaticFactory.getFruitApple();
Fruit.eat();
}
}
工厂方法模式
简单工厂模式仅适用于小型的、业务简单的逻辑中,相对于业务复杂的逻辑并不适用,比如果园日后因为各种原因引入大量不同品种的果树后,不同的人需要不同的水果,会导致园丁(工厂)需要不断的去新增(修改)园丁的技能(工厂方法),这样并不复合设计模式的开闭原则和单一职责原则。所以需要对园丁(工厂方法)进行拆分,将职责进行拆分,将业务进行分发,所以就需要引入了工厂方法模式。
```java
public interface FruitFactory{
public Fruit getFruit(); //获取水果指令
}
public class AppleFactory implements FruitFactory{
@Override
public Fruit getFruit(){
return new Apple();
}
}
public class OrangeFactory implements FruitFactory{
@Override
public Fruit getFruit(){
return new Orange(“name”,100);
}
}
…………
public class FruitTest{
@Autowried
private static FruitFactory fruitFactory;
public static void main(String[] args){
furitFactory = new AppleFactory();
peterdo();
}
public void peterdo(){
Fruit fruit = fruitFactory.getFruit();
Fruit.eat();
………………………
}
}
抽象工厂模式
当果园越做越大,果园主人开始琢磨这自己开店做生意,此时各种水果都需要相应的包装,就会出现以下这种:由于水果品种繁多,包装水果的包装类型同样也多,这就避免不了会出现一种水果被用另一种水果包装的包装方式打包而造成错误。
如果实现的代码还是按照工厂方法的模式进行开发,当每新增一个种类,相应就需要增加相应种类的工厂方法和包装的工厂方法,同时在调用的时候可能会出现上述一种水果被用另一种水果包装的包装方式打包的问题。如以下代码:
public interface FruitFactory{
public Fruit getFruit(); //获取水果指令
}
public class AppleFactory implements FruitFactory{
@Override
public Fruit getFruit(){
return new Apple();
}
}
public class OrangeFactory implements FruitFactory{
@Override
public Fruit getFruit(){
return new Orange(“name”,100);
}
}
public interface BagFactory{
public Bag getPack(); //获取包装指令
}
public class AppleBagFactory implements BagFactory{
@Override
public Bag getPack(){
return new AppleBag();
}
}
public class OrangeBagFactory implements BagFactory{
@Override
public Bag getPack(){
return new OrangeBag(“name”,100);
}
}
@Autowried
public static FruitFactory fruitFactory;
@Autowried
public static BagFactory bagFactory;
public static void pack(){
fruitFactory = new AppleFactory();
Fruit fruit = fruitFactory.getFruit();
bagFactory = new AppleBagFactory();
Bag bag = bagFactory.getBag();
bag.getPack(fruit);
}
考虑到这种情况,这里就需要将包装方法一并交给工厂进行管理,在需要相应的水果同时,相应的包装也同时会出现在这个工厂里面提供调用。
public abstract class AbstractFactory{
public abstract Fruit getFruit();
public abstract Bag getBag();
}
public class AppleFactory extends AbstractFactory{
@Override
public Fruit getFruit(){
return new Apple();
}
@Override
public Bag getBag(){
return new AppleBag();
}
}
public class OrangeFactory extends AbstractFactory{
@Override
public Fruit getFruit(){
return new Orange(“name”,100);
}
@Override
public Bag getBag(){
return new OrangeBag();
}
}
public static void pack(){
AbstractFactory fruitFactory = new AppleFactory();
Fruit fruit = fruitFactory.getFruit();
Bag bag = fruitFactory.getBag();
bag.getPack(fruit);
}
建造者模式
当水果店开始引入折扣的营销概念之后,节假日折扣价和会员价也就一起出现了。
水果套餐类:
//创建一个水果套餐Meal类
public class FruitMeal {
private Apple apple;//苹果--价格
private Banana banana;//香蕉价格
private Orange orange; //桔子价格
private int discount;//折扣价
private int totalPrice;//套餐总价
public void setDiscount(int discount) {
this.discount = discount;
}
public void setApple(Apple apple) {
this.apple = apple;
}
public void setBanana(Banana banana) {
this.banana = banana;
}
public void setOrange(Orange orange) {
this.orange = orange;
}
public int cost(){
return this.totalPrice;
}
public void init() {
if (null != apple){
totalPrice += apple.price();
}
if (null != orange){
totalPrice += orange.price();
}
if (null != banana){
totalPrice += banana.price();
}
if (totalPrice > 0){
totalPrice -= discount;
}
}
public void showItems() {
System.out.println("totalPrice:" + totalPrice);
}
}
建造者类:
//创建一个MealBuilder类,实际的builder类负责创建套餐Meal对象。
public interface Builder {//也是工厂
void buildApple(int price);//设置苹果
void buildBanana(int price);//设置香蕉
void buildOrange(int price);//设置桔子
FruitMeal getFruitMeal();//返回创建的套餐
}
折扣类:
public class HolidayBuilder implements Builder {
private FruitMeal fruitMeal = new FruitMeal();
@Override
public void buildApple(int price) {
Apple apple = new Apple();
apple.setPrice(price);
fruitMeal.setApple(apple);
}
@Override
public void buildBanana(int price) {
Banana fruit = new Banana();
fruit.setPrice(price);
fruitMeal.setBanana(fruit);
}
@Override
public void buildOrange(int price) {
Orange fruit = new Orange("Peter",80);
fruit.setPrice(price);
fruitMeal.setOrange(fruit);
}
@Override
public FruitMeal getFruitMeal() {
fruitMeal.setDiscount(15);//折扣价格对一个套餐来,是固定的
fruitMeal.init();
return fruitMeal;
}
}
public class OldCustomerBuilder implements Builder {
private FruitMeal fruitMeal = new FruitMeal();
@Override
public void buildApple(int price) {
Apple apple = new Apple();
apple.setPrice(price);
fruitMeal.setApple(apple);
}
@Override
public void buildBanana(int price) {
Banana fruit = new Banana();
fruit.setPrice(price);
fruitMeal.setBanana(fruit);
}
@Override
public void buildOrange(int price) {
Orange fruit = new Orange("Peter",80);
fruit.setPrice(price);
fruitMeal.setOrange(fruit);
}
@Override
public FruitMeal getFruitMeal() {
fruitMeal.setDiscount(10);
fruitMeal.init();
return fruitMeal;
}
}
导演类:
public class FruitMealController {//收银台---导演类
public void construct() {
// Builder builder = new HolidayBuilder();
Builder builder = new OldCustomerBuilder();//spring注入方法,
//以下代码模板,轻易是不变的
builder.buildApple(120);//创建苹果设置价格
builder.buildBanana(80);//创建香蕉设置香蕉价格
builder.buildOrange(50);//创建桔子设置价格
FruitMeal fruitMeal = builder.getFruitMeal();
int cost = fruitMeal.cost();
System.out.println("本套件花费:"+cost);
}
public static void main(String[] args) {
new FruitMealController().construct();
}
}
工厂模式总结
工厂模式的原则
1、解耦,把对象的创建和使用过程分开;
2、工厂负责对象的创建,包括其init方法的调用,是黑盒创建过程;
3、面向接口编程,使用者只管使用,只知道其接口而不知其实现类
对比:
1、静态工厂:把所有对象的创建逻辑集中到一个(专业)类中处理,可以应付复杂度低的逻辑中,对于业务量大逻辑复杂的情况需要频繁修改工厂类,不符合设计模式的原则;
2、工厂方法模式:一个工厂负责创建一个产品类的创建,中度业务复杂度可以使用此模式,对于当前只有一个产品类的创建比较适合;
3、抽象工厂模式:将一个系列的产品的工厂合并成一个工厂,负责生产这个系列的产品;
4、对象的创建比较复杂时,按步骤一块块创建,让创建过程模板化。