这里写自定义目录标题
第14章 设计模式
01 练习
(见上一章 最后一项)
02 单例模式
例:
package com.day12;
class SingletonDemo {
//当类被加载时,创建一个实例
//由于每个类只会加载一次,所有能保证创建唯一的对象
private static SingletonDemo instance = new SingletonDemo();
private SingletonDemo() {
}
public static SingletonDemo getInstance() {
return instance;
}
}
public class Day1202 {
public static void main(String[] args){
// SingletonDemo s1 = new SingletonDemo();
// SingletonDemo s2 = new SingletonDemo();
SingletonDemo s1 = SingletonDemo.getInstance();
SingletonDemo s2 = SingletonDemo.getInstance();
System.out.println(s1 == s2); //true
}
}
03 代理模式
代理模式可以在不改变源代码的情况下对目标对象进行访问控制和功能扩展。
目标对象(RealSubject)是实际完成功能的对象。
代理对象(Proxy)是目标对象的替身,用户和RealSubject的交互必须通过Proxy。
去4S店保养车辆,客户经理是代理对象,技术工人是目标对象。
先跟客户经理交互,确认保养的内容。然后客户经理会将保养车辆的工作交给技术工人完成。
当实际工作完成后,再跟客户经理确认并付款。
-
代理对象完成前置工作
-
目标对象完成实际工作
-
代理对象完成后置工作
例:
- 新建一个Interface。 名为:Subject.java
//接口描述了对外提供的功能
public interface Subject {
//修车的工作
void work();
}
- RealSubject.java
public class RealSubject implements Subject {
@Override
public void work() {
System.out.println("RealSubject work");
}
}
- SimpleProxy.java
public class SimpleProxy implements Subject {
//代理对象持有目标对象的引用
private Subject realSubject;
public SimpleProxy() {
realSubject = new RealSubject();
}
@Override
public void work() {
System.out.println("before RealSubject work");//前置工作
realSubject.work();//实际工作委托给目标对象完成
System.out.println("after RealSubject work"); //后置工作
}
}
- ProxyTest.java
public class ProxyTest {
public static void main(String[] args) {
SimpleProxy proxy = new SimpleProxy();
proxy.work();
}
}
04 观察者模式
观察者模式就是发布订阅模式。发布者发布消息后,订阅者就可以得到消息通知。
发布者
抽象的观察者
具体的观察者
4.1 有一个气象站,每天会向观察者推送天气预报。
分析设计如下:
- WeatherObserver.java
//一个接口,抽象的观察者
public interface WeatherObserver {
void update(WeatherData data);
}
- WeatherData.java
//对象是复杂的数据,类是复杂的数据类型
//
public class WeatherData {
// 温度
private int temperature;
// 风力
private int windPower;
public WeatherData(int temperature, int windPower) {
super();
this.temperature = temperature;
this.windPower = windPower;
}
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
public int getWindPower() {
return windPower;
}
public void setWindPower(int windPower) {
this.windPower = windPower;
}
}
- RealObserver.java
//具体的观察者
public class RealObserver implements WeatherObserver {
private String name;
public RealObserver(String name) {
this.name = name;
}
@Override
public void update(WeatherData data) {
System.out.println(name + "收到天气预报数据");
System.out.println("温度:" + data.getTemperature());
System.out.println("风力:" + data.getWindPower());
}
}
- WeatherStation.java
//气象站
public class WeatherStation {
// 定义一个数组来保存注册的观察者
private WeatherObserver[] observers = new WeatherObserver[10];
// 已注册的观察者的数量
private int count = 0;
// 注册观察者
public void reqisterObserver(WeatherObserver observer) {
if (count <= 9) {
observers[count] = observer;
count++;
}
}
// 向已注册的观察者推送天气预报
public void notifyObserver(WeatherData data) {
// 遍历所有的观察者,调用其update方法
for (int i = 0; i < count; i++) {
observers[i].update(data);
}
}
}
- ObserverTest.java
public class ObserverTest {
public static void main(String[] args) {
// 气象站
WeatherStation ws = new WeatherStation();
// 注册观察者
ws.reqisterObserver(new RealObserver("observer1"));
ws.reqisterObserver(new RealObserver("observer2"));
ws.reqisterObserver(new RealObserver("observer3"));
// 天气预报数据
WeatherData data = new WeatherData(12, 2);
// 向已注册的观察者推送天气数据
ws.notifyObserver(data);
}
}
05 模板模式
模板模式就是预先定义一个模板,这个模板包含了一些通用的功能,而将某些特定的实现交给子类或者接口来完成。
去银行办理业务。
办理任何业务都需要:
1.排号
2. 办理具体的业务。
3. 评价。
5.1 去银行办理业务( 使用抽象类的模板模式 )
分析设计如下:
- BankBusinessTemplate.java
public abstract class BankBusinessTemplate {
// 取号
protected long takeNumber() {
// 获取1000以内的随机数字
int r = (int) (Math.random() * 1000);
long number = System.currentTimeMillis() + r;
System.out.println(" 取号" + number);
return number;
}
// 保存客户反馈
protected void saveEvaluation(long number, String evaluation) {
System.out.println("号码:" + number + "的评价:" + evaluation);
}
// 具体的业务,声明为抽象方法,交给子类来做
protected abstract String doAction(long number);
// 业务流程
public void business() {
long number = takeNumber();
String evaluation = doAction(number);
saveEvaluation(number, evaluation);
}
}
- BankBusinessTemplate.java
public class NewCard extends BankBusinessTemplate {
@Override
protected String doAction(long number) {
System.out.println("办理开卡业务");
return "五星好评";
}
}
- LossCard.java
public class LossCard extends BankBusinessTemplate {
@Override
protected String doAction(long number) {
System.out.println("办理挂失业务");
return "五星好评";
}
}
- BankTemplateTest.java
public class BankTemplateTest {
public static void main(String[] args) {
NewCard newCard = new NewCard();
newCard.business();
LossCard lossCard = new LossCard();
lossCard.business();
}
}
tip:
可以方法重写。如:
…
5.2 去银行办理业务( 面向接口的编程 )
- BankBusinessTemplate.java
public class BankBusinessTemplate {
// 取号
protected long takeNumber() {
// 获取1000以内的随机数字
int r = (int) (Math.random() * 1000);
long number = System.currentTimeMillis() + r;
System.out.println(" 取号" + number);
return number;
}
// 保存客户反馈
protected void saveEvaluation(long number, String evaluation) {
System.out.println("号码:" + number + "的评价:" + evaluation);
}
// 业务流程
// 可以接受任何实现BankAction接口的对象作为参数
public void business(BankAction action) {
long number = takeNumber();
// 具体的业务委托给action来实现
String evaluation = action.doAction(number);
saveEvaluation(number, evaluation);
}
}
- NewCard.java
public class NewCard implements BankAction {
@Override
public String doAction(long number) {
System.out.println("办理开卡业务");
return "五星好评";
}
}
- LossCard.java
public class LossCard implements BankAction {
@Override
public String doAction(long number) {
System.out.println("办理挂失业务");
return "五星好评";
}
}
- BankTemplateTest.java
public class BankTemplateTest {
public static void main(String[] args) {
BankBusinessTemplate template = new BankBusinessTemplate();
template.business(new NewCard());
template.business(new LossCard());
}
}
- BankAction.java
//接口Bankaction定义了一个具体业务都需要实现的接口
public interface BankAction {
String doAction(long number);
}
5.3 去银行办理业务( 设计三: 增加“修改手机号” )
- BankBusinessTemplate.java
public class BankBusinessTemplate {
// 取号
protected long takeNumber() {
// 获取1000以内的随机数字
int r = (int) (Math.random() * 1000);
long number = System.currentTimeMillis() + r;
System.out.println(" 取号" + number);
return number;
}
// 保存客户反馈
protected void saveEvaluation(long number, String evaluation) {
System.out.println("号码:" + number + "的评价:" + evaluation);
}
// 业务流程
// 可以接受任何实现BankAction接口的对象作为参数
public void business(BankAction action) {
long number = takeNumber();
// 具体的业务委托给action来实现
String evaluation = action.doAction(number);
saveEvaluation(number, evaluation);
}
}
- NewCard.java
public class NewCard implements BankAction {
@Override
public String doAction(long number) {
System.out.println("办理开卡业务");
return "五星好评";
}
}
- LossCard.java
public class LossCard implements BankAction {
@Override
public String doAction(long number) {
System.out.println("办理挂失业务");
return "五星好评";
}
}
- BankTemplateTest.java
public class BankTemplateTest {
public static void main(String[] args) {
// 模板类
BankBusinessTemplate template = new BankBusinessTemplate();
// 向上类型转换
BankAction a1 = new NewCard();
template.business(a1);
// 向上在型转换
BankAction a2 = new LossCard();
template.business(a2);
template.business(new ChangeNumber());
}
}
- BankAction.java
//接口Bankaction定义了一个具体业务都需要实现的接口
public interface BankAction {
String doAction(long number);
}
- ChangeNumber.java
public class ChangeNumber implements BankAction {
@Override
public String doAction(long number) {
System.out.println("修改手机号");
return "五星好评";
}
}
5.4 练习
练习:
编写一个比较器 比较实现了Areable接口的任意图形的面积。 Circle, Triangle,Rectangle等等。
编写一个测试类,AreaComparatorTest来测试任意图形的比较结果。
public interface Areable {
double getArea();
}
public class AreaComparator {
//a1>a2 返回正数,a1==a2 返回0,a1<a2 返回一个负数
public int compare(Areable a1,Areable a2)
return 0;
}
public class Circle implements Areable {
}
public class AreaComparatorTest{
public static void main(String[] args){
}
}
编码设计:
- Areable.java
public interface Areable {
double getArea();
}
- Rectangle.java
public class Rectangle implements Areable {
private double x;
private double y;
public Rectangle(double x, double y) {
super();
this.x = x;
this.y = y;
}
@Override
public double getArea() {
return x * y;
}
}
- Trangle.java
public class Trangle implements Areable {
private double base;
private double height;
public Trangle(double base, double height) {
super();
this.base = base;
this.height = height;
}
@Override
public double getArea() {
return base * height / 2;
}
}
- AreaComparator.java
public class AreaComparator {
// a1 > a2 返回正数,a1 == a2返回0, a1 < a2返回负数
public int compare(Areable a1, Areable a2) {
if (a1.getArea() > a2.getArea()) {
return 1;
} else if (a1.getArea() < a2.getArea()) {
return -1;
} else {
return 0;
}
}
}
- AreaComparatorTest.java
public class AreaComparatorTest {
public static void main(String[] args) {
Areable a1 = new Rectangle(12, 20);
Areable a2 = new Rectangle(20, 12);
Areable a3 = new Trangle(12, 20);
Areable a4 = new Trangle(20, 12);
AreaComparator comparator = new AreaComparator();
System.out.println(comparator.compare(a1, a2)); // 0
System.out.println(comparator.compare(a3, a4)); // 0
System.out.println(comparator.compare(a1, a3)); // 1
}
}