点咖啡案例:
package factory.before;
public abstract class Coffee {
public abstract String getName();
public void addsugar(){
System.out.println("加糖");
}
public void addMilk(){
System.out.println("加奶");
}
}
package factory.before;
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡类";
}
}
package factory.before;
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
package factory.before;
public class CoffeeStore {
public Coffee orderCoffee(String type){
Coffee coffee=null;
if("american".equals(type))
{
coffee=new AmericanCoffee();
}else if("latte".equals(type))
{
coffee=new LatteCoffee();
}
else {
throw new RuntimeException();
}
coffee.addMilk();
coffee.addsugar();
return coffee;
}
}
public class Client {
public static void main(String[] args) {
CoffeeStore store=new CoffeeStore();
Coffee coffee=store.orderCoffee("latte");
System.out.println(coffee.getName());
}
}
在java中,万物皆对象,如果创建对象的时候直接new该对象,就会对对象耦合严重,假如我们要更换对象,所有new的地方都要修改一遍,显然违背了软件设计的开闭原则。如果使用工厂来生产对象,就和工厂打交道就可以了,彻底和对象解耦。
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行。
package factory.simplefactory;
public abstract class Coffee {
public abstract String getName();
public void addsugar(){
System.out.println("加糖");
}
public void addMilk(){
System.out.println("加奶");
}
}
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡类";
}
}
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
简单工厂模式
简单工厂不是一种设计模式,比较像一种编程习惯。
简单工厂角色包括:
●抽象产品:定义了产品规范,描述了产品的主要特性和功能。
●具体产品:实现或者继承抽象产品的子类。
●具体工厂:提供了创建产品的方法,调用者通过该方法来创建产品。
可以看到,上面的代码已经定义好抽象Coffee类,AmericanCoffee和LatteCoffee分别继承Coffee类。
/*
生产咖啡工厂
* */
public class SimpleCoffeeFactory {
public Coffee createCoffee(String type){
Coffee coffee=null;
// Coffee coffee1=null;
if("american".equals(type))
{
coffee=new AmericanCoffee();
}else if("latte".equals(type))
{
coffee=new LatteCoffee();
}
else {
throw new RuntimeException();
}
coffee.addMilk();
coffee.addsugar();
return coffee;
}
}
/*
咖啡店
* */
public class CoffeeStore {
public Coffee orderCoffee(String type){
SimpleCoffeeFactory factory=new SimpleCoffeeFactory();
Coffee coffee = factory.createCoffee(type);
return coffee;
}
}
public class Client {
public static void main(String[] args) {
CoffeeStore store=new CoffeeStore();
Coffee coffee = store.orderCoffee("latte");
System.out.println(coffee.getName());
}
}
优点:封装了创建对象的过程,可以通过参数直接获取对象。
缺点:增加新产品时还是需要修改工厂类,违背了“开闭原则”。
静态工厂
在开发中,将工厂类的创建对象的功能定义为静态的,这就是静态工厂模式。
public class SimpleCoffeeFactory {
public static Coffee createCoffee(String type){
Coffee coffee=null;
// Coffee coffee1=null;
if("american".equals(type))
{
coffee=new AmericanCoffee();
}else if("latte".equals(type))
{
coffee=new LatteCoffee();
}
else {
throw new RuntimeException();
}
return coffee;
}
}
public class CoffeeStore {
public Coffee orderCoffee(String type){
// SimpleCoffeeFactory factory=new SimpleCoffeeFactory();
// Coffee coffee = factory.createCoffee(type);
/*
无需创建对象,只需调用里面的方法
* */
Coffee coffee = SimpleCoffeeFactory.createCoffee(type);
coffee.addMilk();
coffee.addsugar();
return coffee;
}
}
工厂方法模式:
定义一个创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类实例化延迟到其工厂的子类。
工厂方法模式角色包括:
●抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
●具体工厂:提供了创建产品的方法,调用者通过该方法来创建产品。
●抽象产品:定义了产品规范,描述了产品的主要特性和功能。
●具体产品:实现了抽象产品所定义的接口,由具体工厂来创建。
/*抽象工厂角色接口
* */
public interface CoffeeFactory {
Coffee createCoffee();
}
/*AmericanCoffee工厂
* */
public class AmericanCoffeeFactory implements CoffeeFactory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
/*LatteCoffee工厂
* */
public class LatteCoffeeFactory implements CoffeeFactory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
}
public class CoffeeStore {
private CoffeeFactory factory;
public void setFactory(CoffeeFactory factory){
this.factory=factory;
}
public Coffee orderCoffee(){
Coffee coffee = factory.createCoffee();
coffee.addMilk();
coffee.addsugar();
return coffee;
}
}
public class Client {
public static void main(String[] args) {
CoffeeStore store=new CoffeeStore();
CoffeeFactory factory=new AmericanCoffeeFactory();
store.setFactory(factory);
Coffee coffee = store.orderCoffee();
System.out.println(coffee.getName());
}
}
优点:用户只需知道具体工厂的名称就可以得到所要的产品,无需直到产品具体的创建过程。
缺点:每增加一个产品就要增加一个具体产品类和具体工厂类,增加系统复杂性。
抽象工厂模式
一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无需指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
注:抽象工厂是具体工厂的的升级版,工厂方法只生产一个等级的产品。抽象工厂可生产多等级的产品。
抽象工厂方法模式角色包括:
●抽象工厂:提供了创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品。
●具体工厂:实现抽象工厂的多个抽象方法,完成产品的具体创建。
●抽象产品:定义了产品规范,描述了产品的主要特性和功能,有多个抽象产品。
●具体产品:实现了抽象产品所定义的接口,由具体工厂来创建,多对一。
/*抽象甜品类
* */
public abstract class Dessert {
public abstract void show();
}
public class Trimisu extends Dessert{ @Override public void show() { System.out.println("提拉米斯"); } }
public class MachaMousse extends Dessert{ @Override public void show() { System.out.println("抹茶慕斯"); } }
public interface DessertFactory { /* * 生产咖啡*/ Coffee createCoffee(); Dessert createDessert(); }
public class ItalyDessertFactory implements DessertFactory{ @Override public Coffee createCoffee() { return new LatteCoffee(); } @Override public Dessert createDessert() { return new Trimisu(); } }
public class AmericanDessertFactory implements DessertFactory{ @Override public Coffee createCoffee() { return new AmericanCoffee(); } @Override public Dessert createDessert() { return new MachaMousse(); } }
public class Client {
public static void main(String[] args) {
// CoffeeStore store=new CoffeeStore();
//
// Coffee coffee = store.orderCoffee("latte");
// System.out.println(coffee.getName());
ItalyDessertFactory factory=new ItalyDessertFactory();
Coffee coffee=factory.createCoffee();
Dessert dessert= factory.createDessert();
System.out.println(coffee.getName());
dessert.show();
}
}