5)工厂模式
遵循依赖抽象原则:
变量不要持有具体类的引用;不要让类继承自具体类,要继承自抽象类或接口;不要覆盖基类中已经实现的方法。
5.1 简单工厂模式:
定义了一个创建对象的类,由这个类来封装实例化对象的行为
问题:如一家披萨店,在下订单时会根据不同的披萨实例化不同的对象,这样以后每次提出新品种或者下架某品种,就要去修改订单里面的实例化操作。
如下可以定义一个简单的工厂类来封装实例化过程:
/**
* 简单工厂模式
*/
public class SimplePizzaFactory {
/**
* 传入披萨的类型
*
* @param ordertype
* @return
*/
public Pizza CreatePizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new CheesePizza();
} else if (ordertype.equals("greek")) {
pizza = new GreekPizza();
} else if (ordertype.equals("pepper")) {
pizza = new PepperPizza();
}
return pizza;
}
}
/**
* 披萨订单模块
*/
public class OrderPizza {
SimplePizzaFactory mSimplePizzaFactory;
public OrderPizza(SimplePizzaFactory mSimplePizzaFactory) {
setFactory(mSimplePizzaFactory);
}
public void setFactory(SimplePizzaFactory mSimplePizzaFactory) {
Pizza pizza = null;
String ordertype;
this.mSimplePizzaFactory = mSimplePizzaFactory;
//工厂生产披萨并进行包装发货
do {
ordertype = gettype();
pizza = mSimplePizzaFactory.CreatePizza(ordertype);
if (pizza != null) {
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 PizzaStroe {
public static void main(String[] args) {
SimplePizzaFactory mSimplePizzaFactory;
OrderPizza mOrderPizza;
mOrderPizza=new OrderPizza(new SimplePizzaFactory());
}
}
5.2 方法工厂模式:
定义了一个创建对象的抽象方法,由子类决定要实例化的类。
问题:如果一家披萨店要在全国开连锁,这样地方的配料肯定不一样,所以单纯的将工厂复制过去是不行的。
如下可以将创建披萨的方法抽象化,让子类继承后去实例化具体的对象:
/**
* 抽象化下订单的模块
*/
public abstract class OrderPizza {
public OrderPizza() {
Pizza pizza = null;
String ordertype;
do {
ordertype = gettype();
pizza = createPizza(ordertype);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
abstract Pizza createPizza(String ordertype);
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 LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
/**
* 纽约的披萨店
*/
public class NYOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new NYPepperPizza();
}
return pizza;
}
}
/**
* 披萨店中购买披萨
*/
public class PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza;
mOrderPizza=new NYOrderPizza();
}
}
5.3 抽象工厂模式
定义了一个接口用于创建相关或有依赖关系的对象族,而无需明确指定具体类。
/**
* 抽象工厂模式
*/
public interface AbsFactory {
public Pizza CreatePizza(String ordertype) ;
}
/**
* 伦敦工厂
*/
public class LDFactory implements AbsFactory {
@Override
public Pizza CreatePizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
/**
* 纽约工厂
*/
public class NYFactory implements AbsFactory {
@Override
public Pizza CreatePizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new NYPepperPizza();
}
return pizza;
}
}
/**
* 下订单的模块
*/
public class OrderPizza {
AbsFactory mFactory;
public OrderPizza(AbsFactory mFactory) {
setFactory(mFactory);
}
public void setFactory(AbsFactory mFactory) {
Pizza pizza = null;
String ordertype;
this.mFactory = mFactory;
do {
ordertype = gettype();
pizza = mFactory.CreatePizza(ordertype);
if (pizza != null) {
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 PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza;
mOrderPizza=new OrderPizza(new LDFactory());
}
}
6)策略模式
分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设置行为对象。
策略模式注重功能实现。
原则:分离变化部分,封装接口,基于接口编程各种功能,此模式让行为算法的变化独立于算法的使用者。
将行为定义为接口:
/**
* 飞行
*/
public interface FlyBehavior {
void fly();
}
具体的实现类:
/**
* 会飞
*/
public class GoodFlyBehavior implements FlyBehavior {
@Override
public void fly() {
System.out.println("--GoodFly--");
}
}
/**
* 不会飞
*/
public class NoFlyBehavior implements FlyBehavior {
@Override
public void fly() {
System.out.println("--NoFly--");
}
}
如果还有其他行为也可以向上面一样,先定义接口,在实现,比如叫声可以分呱呱叫还有其他叫。
定义一个鸭子类:
/**
* 鸭子
*/
public abstract class Duck {
/**
* 飞行
*/
FlyBehavior mFlyBehavior;
/**
* 叫声
*/
QuackBehavior mQuackBehavior;
public abstract void display();
public Duck() {
}
public void Fly() {
mFlyBehavior.fly();
}
public void Quack() {
mQuackBehavior.quack();
}
public void SetQuackBehavoir(QuackBehavior qb) {
mQuackBehavior = qb;
}
public void SetFlyBehavoir(FlyBehavior fb) {
mFlyBehavior = fb;
}
public void swim() {
System.out.println("~~im swim~~");
}
}
鸭子下的子类:
/**
* 绿头鸭
*/
public class GreenHeadDuck extends Duck {
public GreenHeadDuck() {
//实例化具体的飞行方式
mFlyBehavior = new GoodFlyBehavior();
//实例化具体的叫声
mQuackBehavior = new GaGaQuackBehavior();
}
@Override
public void display() {
System.out.println("**GreenHead**");
}
}
这样就能实现按不同需求实现:
public class StimulateDuck {
public static void main(String[] args) {
GreenHeadDuck mGreenHeadDuck = new GreenHeadDuck();
RedHeadDuck mRedHeadDuck = new RedHeadDuck();
mGreenHeadDuck.display();
mGreenHeadDuck.Fly();
mGreenHeadDuck.Quack();
mGreenHeadDuck.swim();
mRedHeadDuck.display();
mRedHeadDuck.Quack();
mRedHeadDuck.swim();
mRedHeadDuck.Fly();
}
}
7)模板模式
封装了一个算法步骤,并允许子类为一个或多个步骤方法提供实现;模板模式可以使子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板模式注重步骤实现。
/**
* @author: 肖德子裕
* @date: 2019/03/03 19:31
* @description: 模板模式
*/
public abstract class HotDrinkTemplate {
/**
* 这是一个模板方法
*/
public final void prepareRecipe() {
//烧水,固定
boilWater();
//喝什么,由子类实现
brew();
//加水,固定
pourInCup();
//通过钩子方法,让子类确定是否配料
if (wantCondimentsHook()) {
//加配料
addCodiments();
} else {
System.out.println("不加配料");
}
}
/**
* 钩子方法
*
* @return
*/
public boolean wantCondimentsHook() {
return true;
}
public final void boilWater() {
System.out.println("Boiling water");
}
public abstract void brew();
public final void pourInCup() {
System.out.println("put in cup");
}
public abstract void addCodiments();
}
/**
* @author: 肖德子裕
* @date: 2019/03/03 19:52
* @description: 泡茶
*/
public class TeaWithHook extends HotDrinkTemplate{
@Override
public boolean wantCondimentsHook() {
System.out.println("y/n:");
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String result="";
try {
result=in.readLine();
}catch (IOException e){
e.printStackTrace();
}
if (result.equals("n")){
return false;
}
return true;
}
@Override
public void brew() {
System.out.println("泡茶");
}
@Override
public void addCodiments() {
System.out.println("加柠檬");
}
}
/**
* @author: 肖德子裕
* @date: 2019/03/03 19:58
* @description: 测试
*/
public class Main {
public static void main(String[] args) {
TeaWithHook tea=new TeaWithHook();
tea.prepareRecipe();
}
}
模板方法模式的优点
-
封装不变的内容,扩展可变部分,如果我们要添加一个H3悍马模型,只需要继承父类就可以了。
-
提取公共部分代码,便于维护
-
行为由父类控制,子类实现。基本方法是由子类实现的,因此子类可以通过拓展的方法增加相应的功能,符合开闭原则。
模板方法模式的使用场景
-
多个子类有公有的方法,并且逻辑基本相同时
-
重复、复杂的算法,可以把核心算法设计为模板方法,周边的细节则有各个子类实现
-
代码重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后用钩子方法约束其行为。