设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
设计模式分为三种类型,共23种:
参照Hongyang、菜鸟教程等处文章所写。如有错误欢迎指正,如有侵权,请联系我删除。
定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。
对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。
专题接口:Subject.java ;
/**
* 注册一个观察者
*/
public void registerObserver(Observer observer);
/**
* 移除一个观察者
*/
public void removeObserver(Observer observer);
/**
* 通知所有观察者
*/
public void notifyObservers();
3D服务号的实现类:ObjectFor3D.java
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int index = observers.indexOf(observer);
if (index >= 0) {
observers.remove(index);
}
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(msg);
}
}
/**
* 主题更新信息
*/
public void setMsg(String msg) {
this.msg = msg;
notifyObservers();
}
所有观察者需要实现此接口:Observer.java
public ObserverUser1(Subject subject) {
subject.registerObserver(this);
}
@Override
public void update(String msg) {
Log.e("-----ObserverUser1 ", "得到 3D 号码:" + msg + ", 我要记下来。");
}
// 创建服务号
objectFor3D = new ObjectFor3D();
// 创建两个订阅者
observerUser1 = new ObserverUser1(objectFor3D);
observerUser2 = new ObserverUser2(objectFor3D);
// 两个观察者,发送两条信息
objectFor3D.setMsg("201610121 的3D号为:127");
objectFor3D.setMsg("20161022 的3D号为:000");
简单列一下这个模式的家族:
1、静态工厂模式
2、简单工厂模式(店里买肉夹馍)
public RoujiaMo creatRoujiaMo(String type) {
RoujiaMo roujiaMo = null;
switch (type) {
case "Suan":
roujiaMo = new ZSuanRoujiaMo();
break;
case "La":
roujiaMo = new ZLaRoujiaMo();
break;
case "Tian":
roujiaMo = new ZTianRoujiaMo();
break;
default:// 默认为酸肉夹馍
roujiaMo = new ZSuanRoujiaMo();
break;
}
return roujiaMo;
}
3、工厂方法模式(开分店)
定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。
对比定义:
提供创建肉夹馍店抽象方法:RoujiaMoStore.java
public abstract RoujiaMo sellRoujiaMo(String type);
具体实现抽象方法:XianRoujiaMoStore.java
分店依旧使用简单工厂模式:XianSimpleRoujiaMoFactory.java
4、抽象工厂模式(使用官方提供的原料)
准备时,使用官方的原料:RoujiaMo.java
/**
单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例。
饿汉式[可用]:SingletonEHan.java
含懒汉式[双重校验锁 推荐用]:SingletonLanHan.java
private SingletonLanHan() {}
private static SingletonLanHan singletonLanHanFour;
public static SingletonLanHan getSingletonLanHanFour() {
if (singletonLanHanFour == null) {
synchronized (SingletonLanHan.class) {
if (singletonLanHanFour == null) {
singletonLanHanFour = new SingletonLanHan();
}
}
}
return singletonLanHanFour;
}
内部类[推荐用]:SingletonIn.java
枚举[推荐用]:SingletonEnum.java
策略模式:定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。
最后测试:创建角色:
RoleA roleA = new RoleA("---A");
roleA.setiDisplayBehavior(new DisplayYZ())
.setiAttackBehavior(new AttackXL())
.setiDefendBehavior(new DefendTMS())
.setiRunBehavior(new RunJCTQ());
roleA.display();// 样子
roleA.attack();// 攻击
roleA.run();// 逃跑
roleA.defend();// 防御
定义:将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作。这个定义还好,说适配器的功能就是把一个接口转成另一个接口。
最后测试:给手机冲个电:
Mobile mobile = new Mobile();
V5Power v5Power = new V5PowerAdapter(new V200Power());
mobile.inputPower(v5Power);
定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化: 将请求封装成对象,将动作请求者和动作执行者解耦。)
需求:最近智能家电很火热,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。
1、家电的API:Door.java
2、把命令封装成类:
3、遥控器:ControlPanel.java
4、定义一个命令,可以干一系列的事情:QuickCommand.java
QuickCommand quickCloseCommand = new QuickCommand(new Command[]{new LightOffCommand(light), new ComputerOffCommand(computer), new DoorCloseCommand(door)});
controlPanel.setCommands(6, quickOpenCommand);
controlPanel.keyPressed(6);
5、遥控器面板执行:CommandActivity.java
controlPanel.setCommands(0, new DoorOpenCommand(door));// 开门
controlPanel.keyPressed(0);
装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。
先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。
需求:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:
1、装备的超类:IEquip.java
2、各个装备的实现类:
3、装饰品的超类(装饰品也属于装备):IEquipDecorator.java
4、装饰品的实现类:
5、最后测试:计算攻击力和查看描述:
Log.e("---", "一个镶嵌2颗红宝石,1颗蓝宝石的靴子: ");
IEquip iEquip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
Log.e("---", "攻击力:" + iEquip.caculateAttack());
Log.e("---", "描述语:" + iEquip.description());
定义:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。其实就是为了方便客户的使用,把一群操作,封装成一个方法。
/**
* 一键观影
*/
public void watchMovie() {
computer.on();
light.down();
popcornPopper.on();
popcornPopper.makePopcorn();
projector.on();
projector.open();
player.on();
player.make3DListener();
}
最后测试:一键观影:
new HomeTheaterFacade(computer, light, player, popcornPopper, projector).watchMovie();
定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。
工人的超类:Worker.java
// 具体方法
public final void workOneDay() {
Log.e("workOneDay", "-----------------work start----------------");
enterCompany();
work();
exitCompany();
Log.e("workOneDay", "-----------------work end----------------");
}
// 工作 抽象方法
public abstract void work();
// 钩子方法
public boolean isNeedPrintDate() {
return false;
}
private void exitCompany() {
if (isNeedPrintDate()) {
Log.e("exitCompany", "---" + new Date().toLocaleString() + "--->");
}
Log.e("exitCompany", name + "---离开公司");
}
程序员实现类(可得知时间):ITWorker.java
/**
* 重写父类的此方法,使可以查看离开公司时间
*/
@Override
public boolean isNeedPrintDate() {
return true;
}
最后测试:
查看所有人员的工作情况:
QAWorker qaWorker = new QAWorker("测试人员");
qaWorker();
HRWorker hrWorker = new HRWorker("莉莉姐");
hrWorker.workOneDay();
...
查看程序猿离开公司的时间:
ITWorker itWorker = new ITWorker("jingbin");
itWorker.workOneDay();
定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的。
需求:以自动售货机为例(有已投币、未投币等状态和投币、退币等方法)
最初实现待改进的售货机:VendingMachine.java
改进后的售货机(更具有延展性):VendingMachineBetter.java
// 放钱
public void insertMoney() {
currentState.insertMoney();
}
// 退钱
public void backMoney() {
currentState.backMoney();
}
// 转动曲柄
public void turnCrank() {
currentState.turnCrank();
if (currentState == soldState || currentState == winnerState) {
currentState.dispense();//两种情况会出货
}
}
// 出商品
public void dispense() {
Log.e("VendingMachineBetter", "---发出一件商品");
if (count > 0) {
count--;
}
}
// 设置对应状态
public void setState(State state) {
this.currentState = state;
}
状态的接口:State.java
对应状态的接口实现类:
改进后的售货机测试:
// 初始化售货机,且里面有3个商品
VendingMachineBetter machineBetter = new VendingMachineBetter(3);
machineBetter.insertMoney();
machineBetter.turnCrank();
建造模式是对象的创建模式。建造模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
建造者超类:Builder
public abstract class Builder {
public abstract void setPart(String name, String type);
public abstract Product getProduct();
}
建造者对应实现类:ConcreteBuilder
public class ConcreteBuilder extends Builder {
private Product product = new Product();
@Override
public void setPart(String name, String type) {
product.setName(name);
product.setType(type);
}
@Override
public Product getProduct() {
return product;
}
}
店长Director取汽车:
// 店长
Director director = new Director();
// 得到宝马汽车,内部实现提取宝马汽车的详情操作
Product product = director.getBProduct();
// 展示汽车信息
product.showProduct();
原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
以获取多种形状为例,共分四步:
1、创建一个实现了 Cloneable 接口的抽象类。Shape(implements Cloneable)
public abstract class Shape implements Cloneable {
private String id;
protected String type;
public abstract void draw();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public Object clone() {
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException e) {
Log.e("--", e.getMessage());
}
return object;
}
}
2、创建扩展了上面抽象类的实体类。Circle、Rectangle、Square
public class Circle extends Shape {
public Circle() {
type = "Circle";
}
@Override
public void draw() {
Log.e("---", "Inside Circle::draw() method.");
}
}
3、创建一个类,从数据库获取实体类,并把它们存储在一个 Hashtable 中。ShapeCache
public class ShapeCache {
private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();
public static Shape getShape(String shapeId) {
Shape shapeCache = shapeMap.get(shapeId);
return (Shape) shapeCache.clone();
}
// 对每种形状都运行数据库查询,并创建该形状
// shapeMap.put(shapeKey, shape);
// 例如,我们要添加三种形状
public static void loadCache() {
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(), circle);
Rectangle rectangle = new Rectangle();
rectangle.setId("2");
shapeMap.put(rectangle.getId(), rectangle);
Square square = new Square();
square.setId("3");
shapeMap.put(square.getId(), square);
}
}
4、使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
// 使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
ShapeCache.loadCache();
Shape shapeCache1 = ShapeCache.getShape("1");
Shape shapeCache2 = ShapeCache.getShape("2");
Shape shapeCache3 = ShapeCache.getShape("3");
主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式。由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象。
以随机获取多种形状为例,共分四步:
1、创建一个接口。
public interface Shape {
void draw();
}
2、创建实现接口的实体类。
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color) {
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw() {
Log.e("---", "Circle: Draw() [Color : " + color
+ ", x : " + x + ", y :" + y + ", radius :" + radius);
}
}
3、创建一个工厂,生成基于给定信息的实体类的对象。
public class ShapeFactory {
private static final HashMap<String, Shape> circleMap = new HashMap<String, Shape>();
public static Shape getShape(String color) {
Shape shape = circleMap.get(color);
if (shape == null) {
shape = new Circle(color);
circleMap.put(color, shape);
Log.e("getShape", "Creating circle of color : " + color);
}
return shape;
}
}
4、使用该工厂,通过传递颜色信息来获取实体类的对象。
for (int i = 0; i < 20; i++) {
Circle circle = (Circle) ShapeFactory.getShape(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
一个类代表另一个类的功能。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。可以理解为内存中没有这个对象就创建,有就直接返回这个对象。
以获取磁盘中的图片为例,总共分三步:
1、创建一个接口。
public interface Image {
void display();
}
2、创建实现接口的实体类 RealImage。对应代理类:ProxyImage。
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
private void loadFromDisk(String fileName) {
Log.e("RealImage", "loading " + fileName);
}
@Override
public void display() {
Log.e("RealImage", "Displaying " + fileName);
}
}
public class ProxyImage implements Image {
private String fileName;
private RealImage realImage;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
3、当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。
Image image = new ProxyImage("test_10mb.png");
// 第一次是new的,图像从磁盘加载
image.display();
// 第二次取缓存,图像不需要从磁盘加载
image.display();
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
以画不同颜色的圆为例,实现共分五步:
1、创建桥接实现接口。
public interface DrawAPI {
void drawCircle(int radius, int x, int y);
}
2、创建实现了 DrawAPI 接口的实体桥接实现类。RedCircle、GreenCircle
public class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
Log.e("---", "Drawing Circle[ color: red, radius: "
+ radius + ", x: " + x + ", " + y + "]");
}
}
3、使用 DrawAPI 接口创建抽象类 Shape。
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI) {
this.drawAPI = drawAPI;
}
public abstract void draw();
}
4、创建实现了 Shape 接口的实体类。
public class Circle extends Shape {
private int x, y, radius;
protected Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
drawAPI.drawCircle(radius, x, y);
}
}
5、使用 Shape 和 DrawAPI 类画出不同颜色的圆。
// 画红圆
Circle circle = new Circle(10, 10, 100, new RedCircle());s
circle.draw();
// 画绿圆
Circle circle2 = new Circle(20, 20, 100, new GreenCircle());
circle2.draw();
又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
以创建和打印员工的层次结构为例,最小单元示例:
1、创建 Employee 类,该类带有 Employee 对象的列表。
public class Employee {
private String name;
// 部门
private String dept;
// 工资
private int salary;
// 员工 list
private List<Employee> subordinates;
public Employee(String name, String dept, int salary) {
this.name = name;
this.dept = dept;
this.salary = salary;
this.subordinates = new ArrayList<Employee>();
}
public void add(Employee e) {
subordinates.add(e);
}
public void remove(Employee e) {
subordinates.remove(e);
}
public List<Employee> getSubordinates() {
return subordinates;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", dept='" + dept + '\'' +
", salary=" + salary +
", subordinates=" + subordinates +
'}';
}
}
2.使用 Employee 类来创建和打印员工的层次结构。
final Employee ceo = new Employee("John", "CEO", 30000);
Employee headSales = new Employee("Robert", "Head sales", 20000);
Employee headMarketing = new Employee("Michel", "Head Marketing", 20000);
Employee clerk1 = new Employee("Laura", "Marketing", 10000);
Employee clerk2 = new Employee("Bob", "Marketing", 10000);
Employee salesExecutive1 = new Employee("Richard", "Sales", 10000);
Employee salesExecutive2 = new Employee("Rob", "Sales", 10000);
ceo.add(headSales);
ceo.add(headMarketing);
headSales.add(salesExecutive1);
headSales.add(salesExecutive2);
headMarketing.add(clerk1);
headMarketing.add(clerk2);
Log.e("---", ceo.toString());
// 打印
/*
* Employee{name='John', dept='CEO', salary=30000,
* subordinates=[Employee{name='Robert', dept='Head sales', salary=20000,
* subordinates=[
* Employee{name='Richard', dept='Sales', salary=10000, subordinates=[]},
* Employee{name='Rob', dept='Sales', salary=10000, subordinates=[]}]},
* Employee{name='Michel', dept='Head Marketing', salary=20000,
* subordinates=[Employee{name='Laura', dept='Marketing', salary=10000, subordinates=[]},
* Employee{name='Bob', dept='Marketing', salary=10000, subordinates=[]}]}]}
*/
Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。
以使用迭代器打印名字为例,总共分三步:
1、创建接口:
public interface Iterator {
public boolean hasNext();
public Object next();
}
public interface Container {
public Iterator getIterator();
}
2、创建实现了 Container 接口的实体类。该类有实现了 Iterator 接口的内部类 NameIterator。
public class NameRepository implements Container {
private String names[] = {"John", "jingbin", "youlookwhat", "lookthis"};
@Override
public Iterator getIterator() {
return new NameIterator();
}
private class NameIterator implements Iterator {
int index;
@Override
public boolean hasNext() {
if (index < names.length) {
return true;
}
return false;
}
@Override
public Object next() {
if (hasNext()) {
return names[index++];
}
return null;
}
}
}
3、使用 NameRepository 来获取迭代器,并打印名字。
NameRepository nameRepository = new NameRepository();
for (Iterator iterator = nameRepository.getIterator(); iterator.hasNext(); ) {
String name = (String) iterator.next();
Log.e("---", name);
/*
* /---: John
* /---: jingbin
* /---: youlookwhat
* /---: lookthis
*/
}
用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
以公共聊天室为例,最小单元示例步骤:
1、创建中介类。
public class CharRoom {
public static void showMessage(User user, String message) {
Log.e("---", new Date().toString()
+ " [" + user.getName() + "] : " + message);
}
}
2、创建 user 类。
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sendMessage(String message) {
// 使用中介类
CharRoom.showMessage(this, message);
}
}
3、使用 User 对象来显示他们之间的通信。
User jingbin = new User("jingbin");
jingbin.sendMessage("Hi~ youlookwhat!");
//---: Sun Feb 02 08:11:47 GMT+00:00 2020 [jingbin] : Hi~ youlookwhat!
User jingbin = new User("youlookwhat");
jingbin.sendMessage("Hi~ jingbin!");
//---: Sun Feb 02 08:11:49 GMT+00:00 2020 [youlookwhat] : Hi~ jingbin!
保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
以使用备忘录为例,最小单元步骤:
1、创建 备忘录 Memento 类。
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
2、创建 Originator 类。
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento setSateToMemento() {
return new Memento(state);
}
public String getStateFromMemento(Memento memento) {
return memento.getState();
}
}
3、创建 CareTaker 类。
public class CareTaker {
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
4、使用 CareTaker 和 Originator 对象。
// 管理者
CareTaker careTaker = new CareTaker();
Originator originator = new Originator();
originator.setState("State #1");
originator.setState("State #2");
// 保存状态
careTaker.add(originator.setSateToMemento());
originator.setState("State #3");
// 保存状态
careTaker.add(originator.setSateToMemento());
originator.setState("State #4");
Log.e("---", "Current State: " + originator.getState());
// 得到保存的状态
String fromMemento1 = originator.getStateFromMemento(careTaker.get(0));
Log.e("---", "First Saved State: " + fromMemento1);
String fromMemento2 = originator.getStateFromMemento(careTaker.get(1));
Log.e("---", "Second Saved State: " + fromMemento2);
/*
* /---: Current State: State #4
* /---: First Saved State: State #2
* /---: Second Saved State: State #3
*/
提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
以解释一句话为例,最小单元步骤:
1、创建一个表达式接口 Expression。
public interface Expression {
public boolean interpreter(String content);
}
2、创建实现了上述接口的实体类。TerminalExpression、OrExpression、AndExpression。
public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
@Override
public boolean interpreter(String content) {
// 是包含判断
return content.contains(data);
}
}
public class OrExpression implements Expression {
private Expression expression1;
private Expression expression2;
public OrExpression(Expression expression1, Expression expression2) {
this.expression1 = expression1;
this.expression2 = expression2;
}
@Override
public boolean interpreter(String content) {
return expression1.interpreter(content) || expression2.interpreter(content);
}
}
public class AndExpression implements Expression {
private Expression expression1;
private Expression expression2;
public AndExpression(Expression expression1, Expression expression2) {
this.expression1 = expression1;
this.expression2 = expression2;
}
@Override
public boolean interpreter(String content) {
return expression1.interpreter(content) && expression2.interpreter(content);
}
}
3、使用 Expression 类来创建规则,并解析它们。
/**
* 规则:jingbin 和 youlookwhat 是男性
*/
public static Expression getMaleExpression() {
TerminalExpression jingbin = new TerminalExpression("jingbin");
TerminalExpression youlookwhat = new TerminalExpression("youlookwhat");
return new OrExpression(jingbin, youlookwhat);
}
/**
* 规则:Julie 是一个已婚的女性
*/
public static Expression getMarriedWomanExpression() {
TerminalExpression julie = new TerminalExpression("Julie");
TerminalExpression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}
Expression maleExpression = getMaleExpression();
// jingbin is male: true
Log.e("---", "jingbin is male: " + maleExpression.interpreter("jingbin"));
Expression womanExpression = getMarriedWomanExpression();
// Julie is married woman: true
Log.e("---", "Julie is married woman: " + womanExpression.interpreter("Married Julie"));
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
以Android Studio中打印日志为例,最小单元步骤:
1、创建抽象的记录器类 AbstractLogger。
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
// 责任链中的下一个元素
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message) {
if (this.level <= level) {
write(message);
}
// 递归效果,不断调用下一级 logMessage
if (nextLogger != null) {
nextLogger.logMessage(level, message);
}
}
protected abstract void write(String message);
}
2、创建扩展了该记录器类的实体类。
public class ConsoleLogger extends AbstractLogger {
public ConsoleLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
Log.e("---", "Standard Console::Logger " + message);
}
}
public class FileLogger extends AbstractLogger {
public FileLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
Log.e("---", "File::Logger " + message);
}
}
public class ErrorLogger extends AbstractLogger {
public ErrorLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
Log.e("---", "Error Console::Logger " + message);
}
}
3、创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
public static AbstractLogger getChainOfLoggers() {
ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
FileLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
ConsoleLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);
return errorLogger;
}
AbstractLogger logger = getChainOfLoggers();
// ---: Standard Console::Logger this is an information.
logger.logMessage(AbstractLogger.INFO, "this is an information.");
// ---: File::Logger this is a debug level information.
// ---: Standard Console::Logger this is a debug level information.
logger.logMessage(AbstractLogger.DEBUG, "this is a debug level information.");
// ---: Error Console::Logger this is a error level information.
// ---: File::Logger this is a error level information.
// ---: Standard Console::Logger this is a error level information.
logger.logMessage(AbstractLogger.ERROR, "this is a error level information.");
在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
以显示计算机的组成部分为例,主要分五步实现:
1、定义一个表示元素的接口。
public interface ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
2、创建扩展了上述类的实体类。Keyboard、Monitor、Mouse、Computer
public class Computer implements ComputerPart {
private ComputerPart[] parts;
public Computer() {
this.parts = new ComputerPart[]{new Mouse(), new Keyboard(), new Monitor()};
}
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
for (ComputerPart part : parts) {
part.accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}
public class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
3、定义一个表示访问者的接口。
public interface ComputerPartVisitor {
public void visit(Computer computer);
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
public void visit(Monitor monitor);
}
4、创建实现了上述类的实体访问者。
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@Override
public void visit(Computer computer) {
Log.e("---", "Displaying Computer.");
}
@Override
public void visit(Mouse mouse) {
Log.e("---", "Displaying Mouse.");
}
@Override
public void visit(Keyboard keyboard) {
Log.e("---", "Displaying Keyboard.");
}
@Override
public void visit(Monitor monitor) {
Log.e("---", "Displaying Monitor.");
}
}
5、使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
/*
*打印:
*---: Displaying Mouse.
*---: Displaying Keyboard.
*---: Displaying Monitor.
*---: Displaying Computer.
*/