设计模式之工厂模式

1.工厂模式简介

工厂模式,就是将对象实例化的方法进行提取并封装,放到一个类中进行统一管理维护,达到与主项目降低依赖,降低耦合性。从而提高项目的扩展性和可维护性

假设你去买果汁,直接去果汁店,果汁店会根据你的需求给你做好饮品,直接喝就可以,不用考虑太多,这里的果汁店就类似于一个工厂(或者一个工厂簇),根据你提供的生产出实例(怎么突然想到spring的ioc...)

 

2.工厂模式的实现方法

常见的工厂模式共三种,主要分为

简单工厂模式(静态工厂模式)
工厂方法模式
抽象工厂模式

2-0:需求(后面用工厂模式进行改进)

 

完成各种披萨的生产以及订购任务。

1.披萨的种类有很多,例如(GreekPizza,CheesePizza)等

2.披萨的制作工艺复杂(prepare,bake,cut,box)

3.完成pizza店的订购任务

 

思路:构建一个pizza的抽象类,然后其他pizza去继承该类,达到不同pizza种类的构建。另外构建出orderPizza类,对Pizza进行统一处理

 

优点:比较容易理解,操作简单

 

缺点:违反了设计模式的ocp原则,即对扩展开放,对修改关闭。当我们给类增加新功能的时候,尽量不修改代码或者少修改代码

(比如说需要再添加一种pizza种类,要在源代码的基础上修改很多)

 

UML:

 

 

public abstract class Pizza {
    //名字
    protected String name;

    //准备原材料
    public abstract void prepare();

    //烘烤
    public void bake() {
        System.out.println(name + "baking;");
    }

    //切断
    public void cut() {
        System.out.println(name + "cutting;");
    }

    //打包
    public void box() {
        System.out.println(name + "boxing;");
    }


    public void setName(String name) {
        this.name = name;
    }

}
public class PepperPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("制作PeeperPizza,准备原材料中");
    }
}

public class GreekPizza extends Pizza {

    @Override
    public void prepare() {
        System.out.println("制作GreekPizza,准备原材料中");
    }
}

public class ChessPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("制作ChessPizza,准备原材料中");
    }
}

//简单工厂模式的上述代码一致
//-------------------------------------------------------------------------
//订购pizza
public class OrderPizza {
    public OrderPizza() {
        //违背了迪米特原则
        Pizza pizza = null;
        String orderType;//订购类型
        do {
            orderType = getType();
            if (orderType.equals("greek")) {
                pizza = new GreekPizza();
                pizza.setName(orderType + " pizza ");
            } else if (orderType.equals("cheese")) {
                pizza = new ChessPizza();
                pizza.setName(orderType + " pizza ");
            } else if (orderType.equals("pepper")) {
                pizza = new PepperPizza();
                pizza.setName(orderType + " pizza ");
            } else {
                break;
            }
            //输出pizza制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

        } while (true);
    }

    //获取类型
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

//客户端完成订购任务
public class PizzaStore {
    public static void main(String[] args) {
        OrderPizza pizza = new OrderPizza();
    }
}

 

2-1:简单工厂模式(静态工厂模式)

思路:创建一个工厂类,用来实例化所有对象(pizza实例和上述一致)

 

UML:

 

代码演示:


//简单工厂类(静态工厂)
/**
 *
 * 在一处进行new即可(工厂类) 其他地方直接使用实例 public (static) T createXxx();
 *
 * !!!定义一个可以实例化对象的类,从而去覆盖掉创建对象的代码(代码的重封装)
 * */
//在简单工厂中进行实例的new
public class SimpleFactory {
    //使用简单工厂模式,给出预订类型 创建pizza
    public static Pizza createPizza(String orderType) {
        System.out.println("使用简单工厂模式");
        Pizza pizza = null;
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName(orderType + " pizza ");
        } else if (orderType.equals("cheese")) {
            pizza = new ChessPizza();
            pizza.setName(orderType + " pizza ");
        }
        //增加方法只需要更改一处即可
        else if (orderType.equals("pepper")) {
            pizza = new PepperPizza();
            pizza.setName(orderType + " pizza ");
        }
        return pizza;
    }
}



//订购pizza
public class OrderPizza {

   private Pizza pizza;
   private String orderType;//用户输入

    public void setFactory(){
        do {
            orderType=getType();
            pizza = SimpleFactory.createPizza(orderType);
            if(pizza != null){
                showPizza();
            }
        }while (true);
    }
    //展示
    public void showPizza() {
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
    }
    //获取类型
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}


//客户端完成订购任务
public class PizzaStore {
    public static void main(String[] args) {
        OrderPizza pizza = new OrderPizza();
        //制作完毕
        pizza.setFactory();
    }
}


 

2-2:工厂方法模式

 

假设现在增加需求,在订购pizza的时候可以去选择pizza的产地,该如何改进?

1.依旧使用简单工厂模式,创建不同的工厂实体类用来生产不同的pizza

2.使用工厂方法模式

*将pizza项目的实例化方法 即上述SimpleFactory中的createPizza()方法变成抽象方法,在不同的子类中进行实现

 

工厂方法模式的核心:

如果在实际操作中创建的实例存在父类,子类的形式,可以考虑使用工厂方法模式,定义一个创建子类的抽象方法,由子类决定需要实例的类。工厂方法模式将对象的实例化进行推迟子类

 

代码演示:

//--------实例(来自不同地区不同口味的pizza)------------------------
public abstract class Pizza {
    protected String name; //名字

    //准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
    public abstract void prepare();


    public void bake() {
        System.out.println(name + " baking;");
    }

    public void cut() {
        System.out.println(name + " cutting;");
    }

    //打包
    public void box() {
        System.out.println(name + " boxing;");
    }

    public void setName(String name) {
        this.name = name;
    }
}



public class BJCheesePizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("北京的奶酪pizza");
		System.out.println(" 北京的奶酪pizza 准备原材料");
	}

}

public class BJPepperPizza extends Pizza {
	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("北京的胡椒pizza");
		System.out.println(" 北京的胡椒pizza 准备原材料");
	}
}

public class LDCheesePizza extends Pizza{

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("伦敦的奶酪pizza");
		System.out.println(" 伦敦的奶酪pizza 准备原材料");
	}
}

public class LDPepperPizza extends Pizza{
	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("伦敦的胡椒pizza");
		System.out.println(" 伦敦的胡椒pizza 准备原材料");
	}
}

//--------------------------------------------------------------

public abstract  class OrderPizza {
    //子类实现的抽象方法
    abstract Pizza createPizza(String orderType);

    // 构造器
    public OrderPizza() {
        Pizza pizza = null;
        String orderType; // 订购披萨的类型
        do {
            orderType = getType();
            pizza = createPizza(orderType); //抽象方法,由工厂子类完成
            //输出pizza 制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

        } while (true);
    }



    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

}
//对象的实例化推迟到子类
public class BJOrderPizza extends OrderPizza {


    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            //子类new
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            //子类new
            pizza = new BJPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}
//对象的实例化推迟到子类
public class LDOrderPizza extends OrderPizza {


    //在子类中进行创建
    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            //子类new
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            //子类new
            pizza = new LDPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

// store
public class PizzaStore {
    public static void main(String[] args) {
        String loc = "bj";
        if (loc.equals("bj")) {
            //创建北京口味的各种Pizza
            new BJOrderPizza();
        } else {
            //创建伦敦口味的各种Pizza
            new LDOrderPizza();
        }
        // TODO Auto-generated method stub
    }
}

2-3: 抽象工厂模式

 

介绍:

1.抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合

2.将工厂类抽象为两层,第一层是抽象化的工厂(接口),用于定义工厂的规范,第二层实现具体工厂,生产合适的实例,利于代码的维护和扩展。

 

 

UML:

 

代码实例:

//*********工厂簇*******************8
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    //工厂子类具体实现
    public  Pizza createPizza(String orderType);
}

public class BJFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        //开始生产
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            //子类new
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            //子类new
            pizza = new BJPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }
}

public class LDFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            //子类new
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            //子类new
            pizza = new LDPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }
}

//生产点 调用工厂
public class OrderPizza {
//    private AbsFactory factory;
//    public void setFactory(AbsFactory factory){
//        this.factory = factory;
//    }
    // 写一个方法,可以获取客户希望订购的披萨种类

//生产pizza 多态
    public void productPizza(AbsFactory factory){
        Pizza pizza = null;
        String orderType; // 订购披萨的类型
        do {
            orderType = getType();
            pizza=factory.createPizza(orderType);
            //输出pizza 制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } while (true);
    }


    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

}

//*****************实例*********************

public class PizzaStore {
    public static void main(String[] args) {
        OrderPizza mOrder = new OrderPizza();
        //多态
        mOrder.productPizza(new BJFactory());

    }
}
public class BJPepperPizza extends Pizza {
	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("北京的胡椒pizza");
		System.out.println(" 北京的胡椒pizza 准备原材料");
	}
}
public class LDCheesePizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("伦敦的奶酪pizza");
		System.out.println(" 伦敦的奶酪pizza 准备原材料");
	}
}

public class LDPepperPizza extends Pizza {
	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		setName("伦敦的胡椒pizza");
		System.out.println(" 伦敦的胡椒pizza 准备原材料");
	}
}

public abstract class Pizza {
    protected String name; //名字

    //准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
    public abstract void prepare();


    public void bake() {
        System.out.println(name + " baking;");
    }

    public void cut() {
        System.out.println(name + " cutting;");
    }

    //打包
    public void box() {
        System.out.println(name + " boxing;");
    }

    public void setName(String name) {
        this.name = name;
    }
}

//销售点
//销售点
public class PizzaStore {
    public static void main(String[] args) {
        OrderPizza mOrder = new OrderPizza();
        //多态
        mOrder.productPizza(new BJFactory());

    }
}





3.jdk中的工厂模式 Calender

 

1.在这里截取了部分java.util.calender的源码,能看到Calendar中使用了简单工厂模式的思想,通过getInstance进行实例的创建。

 

2.根据提供的cal,进行不同实例的初始化。

 

3.将这里的代码和上述简单工厂的pizza对比,如果pizza的种类再多,与其使用if else if else,不如使用switch来的清晰。

public static Calendar getInstance()
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }

private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }
        //以此为根据 进行条件判断,从而确定怎样创建实例
        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                //实例化
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                //实例化
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                //实例化
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
       //!!!
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                //实例化
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                //实例化
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {

                //实例化
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }

 

4.总结

tip1:

工厂模式就是将创建实例的方法进行抽离,从而封装为独立的生产类,在这个类中进行各种实例的初始化

 

tip2:

如果组织架构单一,使用简单工厂即可;

如果组织结构复杂(存在父类或者子类的关系),可以将创建实例的方法进行抽象(类似上述的createPizza()),在子类中具体实现(延迟实例的初始化)【抽象方法】

或者将整个工厂进行抽象,作为工厂模板(AbsFactory),从而实例化多个子工厂,聚合或者组合到其他类中。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值