用最简单的例子说明设计模式(二)之模版方法、策略模式、组合模式、观察者模式
模板方法模式
提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。
使用场景
1)多个子类有公有的方法,并且逻辑基本相同时
2)重要、复杂的算法,可以把核心算法设计为模板方法
3)重构时,模板方法模式是一个经常使用的模式
public abstract class AbstractWork { protected void getUp() { System.out.println("起床啦!"); } protected abstract void goToWork(); protected abstract void work(); protected abstract void getOffWork(); /* * TemplateMethod,大家都拥有共同的执行步骤 */ public final void newDay() { getUp(); goToWork(); work(); getOffWork(); } } public class BossWork extends AbstractWork { @Override protected void goToWork() { System.out.println("老板开车去上班"); } @Override protected void work() { System.out.println("老板的分配工作给员工"); } @Override protected void getOffWork() { System.out.println("老板开车去下班"); } } public class StaffWork extends AbstractWork { @Override protected void goToWork() { System.out.println("员工做公交去上班"); } @Override protected void work() { System.out.println("员工处理具体工作"); } @Override protected void getOffWork() { System.out.println("员工做公交下班"); } } public class Test { public static void main(String[] args) { BossWork bossWork = new BossWork(); StaffWork staffWork = new StaffWork(); bossWork.newDay(); System.out.println("------------------------"); staffWork.newDay(); } }
策略模式
定义了算法家庭,分别封装起来。让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
一个类定义了多种行为,并且这些行为在这个类的方法中以多个条件语句的形式出现,那么可以使用策略模式避免在类中使用大量的条件语句。
public interface AbstractStrategy { //按距离来计算价格 int calculatePrice(int km); } public class BusStrategy implements AbstractStrategy { @Override public int calculatePrice(int km) { int extraTotal = km - 10; int extraFactor = extraTotal / 5; int fraction = extraTotal % 5; int price = 1 + extraTotal % 5; return fraction > 0 ? ++price : price; } } public class TaxiStrategy implements AbstractStrategy { @Override public int calculatePrice(int km) { return km * 2; } } public class Context { private AbstractStrategy strategy; public void setStrategy(AbstractStrategy strategy) { this.strategy = strategy; } public int calclatePrice(int km) { return strategy.calculatePrice(km); } public static void main(String[] strings) { Context calculator = new Context(); calculator.setStrategy(new BusStrategy()); // calculator.setStrategy(new TaxiStrategy()); System.out.println("公交车20km价格:" + calculator.calclatePrice(20)); } }
传统写法
//PriceCalculator 类很明显的问题就是并不是单一职责,首先它承担计算公交车和地铁乘坐价格的职责, //另一个问题就是通过if-else的形式来判断使用哪种计算形式。当我们增加一种出行方式时,如出租车, //那么我们就需要在PriceCalculator 中增加一个方法来计算出租车出行的价格,并且在calculatePrice(int km, int type)函数增加一个判断 public static class PriceCalculator { private static final int TAXI = 3; private static final int BUS = 1; private static final int SUBWAY = 2; public static void main(String[] strings) { PriceCalculator calculator = new PriceCalculator(); System.out.println("做20km公交票价:" + calculator.calculatePrice(20, BUS)); System.out.println("做20km地铁票价:" + calculator.calculatePrice(20, SUBWAY)); } private int busPrice(int km) { return km * 1; } public int taxiPrice(int km) { return km * 7; } /** * 根据不同类型计算 */ int calculatePrice(int km, int type) { if (type == BUS) { return busPrice(km); } else if (type == SUBWAY) { return taxiPrice(km); } return 0; } }
组合模式
使用户对单个对象和组合对象的使用具有一致性。将对象组合成树形结构以表示“部分-整体”的层次结构。
Component : 组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。
Leaf : 表示叶节点对象。叶子节点没有子节点。
Composite : 定义枝节点行为,用来存储子部件,在 Component 接口中实现与子部件相关的操作。例如 Add 和 Remove
public abstract class File { private String name; public File(String name) { this.name = name; } //操作方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract void watch(); //组合方法 public void add(File file) { throw new UnsupportedOperationException(); } public void remove(File file) { throw new UnsupportedOperationException(); } public File getChild(int position) { throw new UnsupportedOperationException(); } } public class Folder extends File { private List<File> mFileList; public Folder(String name) { super(name); mFileList = new ArrayList<>(); } @Override public void watch() { StringBuffer fileName = new StringBuffer(); for (File file : mFileList) { fileName.append(file.getName() + ";"); } System.out.println("组合模式:这是一个叫" + getName() + "文件夹,包含" + mFileList.size() + "个文件,分别是:" + fileName); } @Override public void add(File file) { mFileList.add(file); } @Override public void remove(File file) { mFileList.remove(file); } @Override public File getChild(int position) { return mFileList.get(position); } } public class TextFile extends File { public TextFile(String name) { super(name); } @Override public void watch() { System.out.println("组合模式:这是一个叫" + getName() + "文本文件"); } } public class testComposite { public static void main(String[] strings) { TextFile textFileA = new TextFile("a.txt"); TextFile textFileB = new TextFile("b.txt"); TextFile textFileC = new TextFile("c.txt"); textFileA.watch(); // textFileA.add(textFileB);//调用会抛我们在抽象接口中写的异常 Folder folder = new Folder("学习资料"); folder.add(textFileA); folder.add(textFileB); folder.add(textFileC); folder.watch(); folder.getChild(1).watch(); Folder folder1 = new Folder("个人资料"); folder1.add(textFileA); folder1.add(textFileB); //可以随便组合 Folder folder2 = new Folder("D盘资料"); folder2.add(folder); folder2.add(folder1); } }
观察者模式
定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆可得到通知并被自动更新。
观察者模式在android中的实际运用:回调模式
回调模式:实现了抽象类/接口的实例实现了父类的提供的抽象方法后,将该方法交还给父类来处理。
例如:通过 setOnClickListener() 方法,Button 持有 OnClickListener 的引用(这一过程没有在图上画出);当用户点击时,Button 自动调用 OnClickListener 的 onClick() 方法。另外,如果把这张图中的概念抽象出来(Button(view) -> 被观察者、OnClickListener -> 观察者、setOnClickListener() -> 订阅,onClick() -> 事件),就由专用的观察者模式(例如只用于监听控件点击)转变成了通用的观察者模式。
public class ObserverPattern { public interface Observer { void update(String state); } public class ConcreteObserver implements Observer { // 观察者状态 private String observerState; @Override public void update(String state) { // 更新观察者状态,让它与目标状态一致 observerState = state; System.out.println("ConcreteObserver State :" + observerState); } } /** * 抽象订阅者(目标者) * 被观察者 * */ public abstract class Subject { // 保存注册的观察者对象 private List<Observer> mObservers = new ArrayList<>(); //注册观察者对象 public void attach(Observer observer) { mObservers.add(observer); System.out.println("Attached an observer"); } //注销观察者对象 public void detach(Observer observer) { mObservers.remove(observer); } // 通知所有注册的观察者对象 public void nodifyObservers(String newState) { for (Observer observer : mObservers) { observer.update(newState); } } } public class ConcreteSubject extends Subject { private String state; public String getState() { return state; } public void change(String newState) { state = newState; System.out.println("ConcreteSubject State:" + state); //状态发生改变,通知观察者 nodifyObservers(state); } } public static void main(String[] args) { ObserverPattern observerPattern = new ObserverPattern(); ConcreteSubject concreteSubject = observerPattern.new ConcreteSubject(); Observer observer1 = observerPattern.new ConcreteObserver(); Observer observer2 = observerPattern.new ConcreteObserver(); // 将观察者对象注册到目标对象上 concreteSubject.attach(observer1); concreteSubject.attach(observer2); // 改变目标对象的状态 concreteSubject.change("I change"); } }
相关源码:
https://github.com/peiniwan/DesignPattern.git