1、策略模式(strategy)- 策略在于选择
使用场景: 目标相同,具体行为不同的场景。例如:吃饭,睡觉,喝水等,不同的人,对于吃有不同的口味,吃就是一个抽象,不同人吃不同口味就是具体行为。但是饭店不可能为每个人按照各自口味做,因此有大众口味,特定口味,定制口味等,这样就限制了具体行为的数量,解决了资源。
策略模式实现需要三部分:
1、要实现不同策略对象的抽象:具体可以是接口或抽象类
2、不同策略的具体实现:继承或实现其抽象
3、策略代理:构造注入策略抽象,具体方法执行策略
本例中,策略抽象为Travel接口,有三种不同具体策略实现,分别是Fly、Train、Car。策略代理类为TravelStrategy,采用java三大特性之一的封装方式,封装策略抽象Travel,构造器可注入具体实现,执行逻辑为start()方法,对外屏蔽了不同策略具体实现,易扩展不同策略。
源码:
顶层抽象Travel.java
package com.design;
public interface Travel {
public String travelTool();
}
具体策略实现
Fly.java
package com.design;
public class Fly implements Travel {
@Override
public String travelTool() {
return "fly";
}
}
Train.java
package com.design;
public class Train implements Travel {
@Override
public String travelTool() {
return "train";
}
}
Car.java
package com.design;
public class Car implements Travel {
@Override
public String travelTool() {
return "car";
}
}
策略代理
TravelStrategy.java
package com.design;
public class TravelStrategy {
private Travel travel;
public TravelStrategy(Travel travel)
{
this.travel = travel;
}
public void start()
{
String tool = travel.travelTool();
System.out.println("I will take a travel, the means of transportation is " + tool);
}
}
测试:
package com.design;
public class Main {
public static void main(String[] args)
{
Travel tool = new Fly();
TravelStrategy strategy = new TravelStrategy(tool);
strategy.start();
}
}
结果:I will take a travel, the means of transportation is fly
2、模板模式(Template)- 模板在于搭框架
使用场景:当你需要做一个什么时,但又不知道具体怎么做,这时,可以使用模板描述抽象功能,具体实现以后补充即可。
模板模式主要是定义模板:
1、模板中主要包含抽象方法和执行该抽象方法的具体方法
2、java中,可使用接口或抽象类定义模板
实例: 定义一个任务模板Task,其中有抽象方法task(),具体执行task的run()方法。
Task.java
package com.template;
public interface Task {
default void run()
{
task();
}
public void task();
}
具体任务实现
FileTask.java
package com.template;
public class FileTask implements Task {
@Override
public void task() {
System.out.println("file task start...");
}
}
测试
package com.template;
public class Main {
public static void main(String[] args)
{
Task task = new FileTask();
task.run();
}
}
3、观察者模式(Observer)- 观察者在于注册通知
使用场景:状态依赖变更场景,观察者作为中间人,解耦了被观察者和被通知者。
要点:
观察者
1、可被被通知者注册,持有被通知者引用
2、通知所有注册者,触发被通知者状态接收接口
被观察者
1、持有观察者引用
2、某一状态变更时,触发观察者通知接口
被通知者
1、状态接收接口
源码:
观察者
PriceObserver.java
package com.observer;
import java.util.Vector;
public class PriceObserver {
Vector<Costomer> COSTOMERS = new Vector<>();
public void register(Costomer costomer)
{
COSTOMERS.add(costomer);
}
public void notifing()
{
for (Costomer costomer : COSTOMERS)
{
costomer.priceReduction();
}
}
}
被通知者:接口编程
Costomer.java
package com.observer;
public interface Costomer {
public void priceReduction();
}
ACostomer.java
package com.observer;
public class ACostomer implements Costomer{
@Override
public void priceReduction() {
System.out.println("I am A, I know the price is down!");
}
}
BCostomer.java
package com.observer;
public class BCostomer implements Costomer {
@Override
public void priceReduction() {
System.out.println("I am B, I know the price is down!");
}
}
被观察者
Commodity.java
package com.observer;
public class Commodity {
private String name;
private int price;
//观察者引用
private PriceObserver priceObserver;
public Commodity(String name, int price)
{
this.name = name;
this.price = price;
}
public void setPrice(int price) {
this.price = price;
//通知
priceObserver.notifing();
}
public void setPriceObserver(PriceObserver priceObserver) {
this.priceObserver = priceObserver;
}
}
测试
package com.observer;
public class Main {
public static void main(String[] args)
{
Costomer a = new ACostomer();
Costomer b = new BCostomer();
PriceObserver observer = new PriceObserver();
observer.register(a);
observer.register(b);
Commodity apple = new Commodity("Apple", 6999);
apple.setPriceObserver(observer);
//修改价格,降价
apple.setPrice(5999);
}
}
结果:
I am A, I know the price is down!
I am B, I know the price is down!