目录
1、设计原则
1.1 开闭原则
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。以书店卖书为例:
public interface IBook {
String getName();
int getPrice();
String getAuthor();
}
public class NovelBook implements IBook {
private String name;
private int price;
private String author;
@Override
public String getName() {
return this.name;
}
@Override
public int getPrice() {
return this.price;
}
@Override
public String getAuthor() {
return this.author;
}
public NovelBook(String name, int price, String author) {
this.name = name;
this.price = price;
this.author = author;
}
}
public class BookStore {
private final static List<IBook> bookList = new ArrayList<>();
static {
bookList.add(new NovelBook("《天龙八部》", 100, "金庸"));
bookList.add(new NovelBook("《巴黎圣母院》", 200, "雨果"));
bookList.add(new NovelBook("《悲惨世界》", 300, "雨果"));
bookList.add(new NovelBook("《金瓶梅》", 400, "兰陵笑笑生"));
}
public static void main(String[] args) {
NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
numberFormat.setMaximumFractionDigits(2);
System.out.println("-----------书店卖出去的书籍记录如下:-----------");
for (IBook book : bookList) {
System.out.println("书籍名称:" + book.getName() + "\t书籍作者:" + book.getAuthor()
+ "\t书籍价格:" + numberFormat.format(book.getPrice() / 100.0) + "元");
}
}
}
运行结果:
-----------书店卖出去的书籍记录如下:-----------
书籍名称:《天龙八部》 书籍作者:金庸 书籍价格:¥100.00元
书籍名称:《巴黎圣母院》 书籍作者:雨果 书籍价格:¥200.00元
书籍名称:《悲惨世界》 书籍作者:雨果 书籍价格:¥300.00元
书籍名称:《金瓶梅》 书籍作者:兰陵笑笑生 书籍价格:¥400.00元
假设现在需要打折,有以下几种方案:
在IBook上新增加一个方法getOffPrice(),专门用于进行打折处理,所有的实现类实现该方法。但是这样修改的后果就是,实现类NovelBook要修改,BookStore中的main方法也修改。因此,该方案否定。
修改NovelBook类中的方法,直接在getPrice()中实现打折处理。该方法在项目有明确的章程(团队内约束)或优良的架构设计时,是一个非常优秀的方法,但是该方法还是有缺陷的。例如采购书籍人员也是要看价格的,由于该方法已经实现了打折处理价格,因此采购人员看到的也是打折后的价格,会因信息不对称而出现决策失误的情况。因此,该方案也不是一个最优的方案。
增加一个子类OffNovelBook,覆写getPrice方法,高层次的模块(也就是static静态模块 区)通过OffNovelBook类产生新的对象,完成业务变化对系统的最小化开发。好办法,修改也少,风险也小。
public class OffNovelBook extends NovelBook {
public OffNovelBook(String _name, int _price, String _author) {
super(_name, _price, _author);
}
//覆写销售价格
@Override
public int getPrice() {
//原价
int selfPrice = super.getPrice();
int offPrice = 0;
if (selfPrice > 4000) {
//原价大于40元,则打9折
offPrice = selfPrice * 90 / 100;
} else {
offPrice = selfPrice * 80 / 100;
}
return offPrice;
}
}
修改BookStore静态代码块,进行打折
public class BookStore {
private final static List<IBook> bookList = new ArrayList<>();
static {
bookList.add(new OffNovelBook("《天龙八部》", 3200, "金庸"));
bookList.add(new OffNovelBook("《巴黎圣母院》", 5600, "雨果"));
bookList.add(new OffNovelBook("《悲惨世界》", 3500, "雨果"));
bookList.add(new OffNovelBook("《金瓶梅》", 4300, "兰陵笑笑生"));
}
public static void main(String[] args) {
NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
numberFormat.setMaximumFractionDigits(2);
System.out.println("-----------书店卖出去的书籍记录如下:-----------");
for (IBook book : bookList) {
System.out.println("书籍名称:" + book.getName() + "\t书籍作者:" + book.getAuthor()
+ "\t书籍价格:" + numberFormat.format(book.getPrice() / 100.0) + "元");
}
}
}
运行结果:
-----------书店卖出去的书籍记录如下:-----------
书籍名称:《天龙八部》 书籍作者:金庸 书籍价格:¥25.60元
书籍名称:《巴黎圣母院》 书籍作者:雨果 书籍价格:¥50.40元
书籍名称:《悲惨世界》 书籍作者:雨果 书籍价格:¥28.00元
书籍名称:《金瓶梅》 书籍作者:兰陵笑笑生 书籍价格:¥38.70元
1.2 单一职责原则
一个类应该有且仅有一种原因引起改变。
1.3 里式替换原则
所有引用基类的地方必须能透明地使用其子类的对象。
1.4 接口隔离原则
客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。
1.5 最小知道原则(迪米特法则)
一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。以清点学生人数为例(反例):
public class Teacher {
//老师对学生发布命令,清一下女生
public void command(GroupLeader groupLeader) {
List listGirls = new ArrayList();
//初始化女生
for (int i = 0; i < 20; i++) {
listGirls.add(new Girl());
}
//告诉体育委员开始执行清查任务
groupLeader.countGirls(listGirls);
}
}
public class GroupLeader {
//清查女生数量
public void countGirls(List<Girl> listGirls) {
System.out.println("女生数量是:" + listGirls.size());
}
}
public class Girl {
}
public class Client {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.command(new GroupLeader());
}
}
运行结果:
女生数量是:20
迪米特法则告诉我们一个类只和朋友类交流,但是我们刚刚定义的commond方法却与Girl类有了交流,声明了一个List<Girls>动态数组,也就是与一个陌生的类Girl有了交流, 这样就破坏了Teacher的健壮性。方法是类的一个行为,类竟然不知道自己的行为与其他类产生依赖关系,这是不允许的,严重违反了迪米特法则,需要进行优化:
public class Teacher {
//老师对学生发布命令,清一下女生
public void command(GroupLeader groupLeader) {
//告诉体育委员开始执行清查任务
groupLeader.countGirls();
}
}
public class GroupLeader {
private List<Girl> listGirls;
public GroupLeader(List<Girl> listGirls) {
this.listGirls = listGirls;
}
//清查女生数量
public void countGirls() {
System.out.println("女生数量是:" + listGirls.size());
}
}
public class Client {
public static void main(String[] args) {
List<Girl> listGirls = new ArrayList<>();
//初始化女生
for (int i = 0; i < 20; i++) {
listGirls.add(new Girl());
}
Teacher teacher = new Teacher();
teacher.command(new GroupLeader(listGirls));
}
}
运行结果:
女生数量是:20
对程序进行了简单的修改,把Teacher中对List<Girl>的初始化移动到了场景类中,同时在GroupLeader中增加了对Girl的注入,避开了Teacher类对陌生类Girl的访问,降低了系统间的耦合,提高了系统的健壮性。
1.6 依赖倒置原则
程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。以司机开车为例(反例):
public class Driver {
//司机的主要职责就是驾驶汽车
public void drive(Benz benz) {
benz.run();
}
}
public class Benz {
//汽车肯定会跑
public void run() {
System.out.println("奔驰汽车开始运行...");
}
}
public class Client {
public static void main(String[] args) {
Driver zhangSan = new Driver();
Benz benz = new Benz();
//张三开奔驰车
zhangSan.drive(benz);
}
}
运行结果:
奔驰汽车开始运行...
通过以上的代码,完成了司机开动奔驰车的场景,到目前为止,这个司机开奔驰车的项目没有任何问题。但是如果我们在一段貌似磐石的程序上加上一块小石头:张三司机不仅要开奔驰车,还要开宝马车,这样就无法实现了,因为张三没有开宝马车的方法?一个拿有C驾照的司机竟然只能开奔驰车而不能开宝马车,这也太不合理了!在 现实世界都不允许存在这种情况,何况程序还是对现实世界的抽象,我们的设计出现了问题:司机类和奔驰车类之间是紧耦合的关系,其导致的结果就是系统的可维护性和可读性大大降低。根据依赖倒置原则优化后:
public class Driver {
private ICar car;
//司机的主要职责就是驾驶汽车
public void drive() {
car.run();
}
public void setCar(ICar car) {
this.car = car;
}
}
public interface ICar {
void run();
}
public class Benz implements ICar{
//汽车肯定会跑
@Override
public void run() {
System.out.println("奔驰汽车开始运行...");
}
}
public class BMW implements ICar {
//宝马车当然也可以开动了
@Override
public void run() {
System.out.println("宝马汽车开始运行...");
}
}
public class Client {
public static void main(String[] args) {
Driver zhangSan = new Driver();
//张三开奔驰车
zhangSan.setCar(new Benz());
zhangSan.drive();
//张三开宝妈车
zhangSan.setCar(new BMW());
zhangSan.drive();
}
}
运行结果:
奔驰汽车开始运行...
宝马汽车开始运行...
2、单例模式
2.1 饿汉模式
/**
* 饿汉模式
* 优点:线程安全,调用时效率高
* 缺点:不管是否使用都创建对象,可能造成资源浪费
*/
package singleton;
public class Hungry {
private Hungry(){}
private static Hungry hungry = new Hungry();
public static Hungry getInstance(){
return hungry;
}
}
2.2 懒汉模式
/**
* 非线程安全的懒汉模式
* 优点:调用时才创建对象,不会浪费资源
* 缺点:非线程安全
*/
package singleton;
public class LazyNotSafe {
private LazyNotSafe(){}
private static LazyNotSafe lazyNotSafe;
public static LazyNotSafe getInstance(){
if(lazyNotSafe == null){
lazyNotSafe = new LazyNotSafe();
}
return lazyNotSafe;
}
}
2.3 加锁懒汉模式
/**
* 线程安全的懒汉模式
* 优点:线程安全
* 缺点:方法锁,效率较低
*/
package singleton;
public class LazySync{
private LazySync(){}
private static LazySync lazySync;
public static synchronized LazySync getInstance(){
if(lazySync == null){
lazySync = new LazySync();
}
return lazySync;
}
}
2.4 双重检查锁
/**
* 双重检查锁懒汉模式,线程安全,效率较高
* 优点:线程安全,效率较高
* 注意:lazyDoubleLock对象需要加volatile关键字,禁止JVM指令重排,否则可能导致返回未创建好的对象
*/
package singleton;
public class LazyDoubleLock {
private LazyDoubleLock(){}
private static volatile LazyDoubleLock lazyDoubleLock;
public static LazyDoubleLock getInstance(){
if(lazyDoubleLock == null){
synchronized (LazyDoubleLock.class){
if(lazyDoubleLock == null){
lazyDoubleLock = new LazyDoubleLock();
}
}
}
return lazyDoubleLock;
}
}
2.5 静态内部类
/**
* 静态内部类
* 优点:线程安全,效率较高,
* 缺点:
*/
package singleton;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class StaticInner implements Serializable {
private StaticInner(){
//构造器判断,防止反射攻击
if(InnerInstance.STATIC_INNER != null){
throw new IllegalStateException();
}
}
private Object readResolve() throws ObjectStreamException {
return InnerInstance.STATIC_INNER;
}
public static StaticInner getInstance(){
return InnerInstance.STATIC_INNER;
}
private static class InnerInstance{
private static final StaticInner STATIC_INNER = new StaticInner();
}
}
2.6 枚举
/**
* 枚举
* 优点:都是
* 缺点:写起来不习惯
*/
package singleton;
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
3、工厂模式
public interface IMilk {
}
public class Mengniu implements IMilk {
public Mengniu(){
System.out.println("生产蒙牛");
}
}
public class Jindian implements IMilk {
public Jindian() {
System.out.println("生产金典");
}
}
public class Telunsu implements IMilk {
public Telunsu() {
System.out.println("生产特仑苏");
}
}
3.1 简单工厂模式
public class SimpleMilkFactory {
public IMilk createMilk(String name) {
if ("Telunsu".equals(name)) {
return new Telunsu();
} else if ("Jindian".equals(name)) {
return new Jindian();
} else if ("Mengniu".equals(name)) {
return new Mengniu();
} else {
System.out.println("不支持生产");
return null;
}
}
}
public class SimpleFactoryDemo {
public static void main(String[] args) {
SimpleMilkFactory simpleMilkFactory = new SimpleMilkFactory();
IMilk mengniu = simpleMilkFactory.createMilk("Mengniu");
IMilk jindian = simpleMilkFactory.createMilk("Jindian");
IMilk telunsu = simpleMilkFactory.createMilk("Telunsu");
}
}
运行结果:
生产蒙牛
生产金典
生产特仑苏
3.2 工厂方法模式
public interface IMethodMilkFactory {
IMilk createMilk();
}
public class JindianMilkFactory implements IMethodMilkFactory {
@Override
public IMilk createMilk() {
return new Jindian();
}
}
public class MengniuMilkFactory implements IMethodMilkFactory {
@Override
public IMilk createMilk() {
return new Mengniu();
}
}
public class TelunsuMilkFactory implements IMethodMilkFactory {
@Override
public IMilk createMilk() {
return new Telunsu();
}
}
public class MethodFactoryDemo {
public static void main(String[] args) {
IMethodMilkFactory jindianMilkFactory = new JindianMilkFactory();
jindianMilkFactory.createMilk();
IMethodMilkFactory mengniuMilkFactory = new MengniuMilkFactory();
mengniuMilkFactory.createMilk();
IMethodMilkFactory telunsuMilkFactory = new TelunsuMilkFactory();
telunsuMilkFactory.createMilk();
}
}
运行结果:
生产蒙牛
生产金典
生产特仑苏
4、代理模式
public interface ITarget {
void doSomething();
}
public class Target implements ITarget{
@Override
public void doSomething() {
System.out.println("目标对象执行任务");
}
}
4.1 静态代理
public class StaticProxy implements ITarget {
private Target target;
public StaticProxy(Target target) {
this.target = target;
}
@Override
public void doSomething() {
System.out.println("代理对象执行任务");
target.doSomething();
}
}
public class StaticProxyDemo {
public static void main(String[] args) {
Target target = new Target();
ITarget staticProxy = new StaticProxy(target);
staticProxy.doSomething();
}
}
运行结果:
代理对象执行任务
目标对象执行任务
4.2 动态代理
4.2.1 JDK动态代理
public class JdkDynamicInvocationHandler implements InvocationHandler {
private Object object;
public JdkDynamicInvocationHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理对象执行任务");
Object result = method.invoke(this.object, args);
return result;
}
}
public class JdkDynamicDemo {
public static void main(String[] args) {
Target target = new Target();
ITarget proxy = (ITarget)Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new JdkDynamicInvocationHandler(target));
proxy.doSomething();
}
}
运行结果:
代理对象执行任务
目标对象执行任务
4.2.2 CGLIB动态代理
public class CglibMethodInterceptor implements MethodInterceptor {
private Object object;
public CglibMethodInterceptor(Object object) {
this.object = object;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理对象执行任务");
Object result = method.invoke(object, objects);
return result;
}
}
public class CglibDynamicDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Target.class);
enhancer.setCallback(new CglibMethodInterceptor(new Target()));
Target target = (Target)enhancer.create();
target.doSomething();
}
}
执行结果:
代理对象执行任务
目标对象执行任务
5、策略模式
public interface Pay {
void pay();
}
public class AliPay implements Pay {
@Override
public void pay() {
System.out.println("支付宝支付");
}
}
public class WeChatPay implements Pay {
@Override
public void pay() {
System.out.println("微信支付");
}
}
public class QuickPassPay implements Pay {
@Override
public void pay() {
System.out.println("云闪付支付");
}
}
public class StrategyContext {
private Pay pay;
public StrategyContext (Pay pay) {
this.pay = pay;
}
public void dealPay() {
pay.pay();
}
}
public class StrategyDemo {
public static void main(String[] args) {
StrategyContext aliPayStrategyContext = new StrategyContext(new AliPay());
aliPayStrategyContext.dealPay();
StrategyContext weChatPayStrategyContext = new StrategyContext(new WeChatPay());
weChatPayStrategyContext.dealPay();
StrategyContext quickPassPayStrategyContext = new StrategyContext(new QuickPassPay());
quickPassPayStrategyContext.dealPay();
}
}
运行结果:
支付宝支付
微信支付
云闪付支付
6、模板方法模式
public abstract class AbstractTemplate {
public void init(){
System.out.println("执行初始化方法");
}
abstract void doSomething1();
public void hookMethod(){}
abstract void doSomething2();
public void destroy() {
System.out.println("执行结束方法");
}
public void template() {
init();
doSomething1();
hookMethod();
doSomething2();
destroy();
}
}
public class TemplateObjectA extends AbstractTemplate {
@Override
public void doSomething1() {
System.out.println("模板A执行方法1");
}
@Override
public void hookMethod() {
System.out.println("模板A执行钩子方法");
}
@Override
public void doSomething2() {
System.out.println("模板A执行方法2");
}
}
public class TemplateObjectB extends AbstractTemplate {
@Override
void doSomething1() {
System.out.println("模板B执行方法1");
}
@Override
void doSomething2() {
System.out.println("模板B执行方法2");
}
}
public class TemplateDemo {
public static void main(String[] args) {
TemplateObjectA templateObjectA = new TemplateObjectA();
TemplateObjectB templateObjectB = new TemplateObjectB();
templateObjectA.template();
System.out.println("-----");
templateObjectB.template();
}
}
运行结果:
执行初始化方法
模板A执行方法1
模板A执行钩子方法
模板A执行方法2
执行结束方法
-----
执行初始化方法
模板B执行方法1
模板B执行方法2
执行结束方法
7、原型模式
@Data
public class ProtoObject implements Cloneable, Serializable {
private List<String> list = new ArrayList<>();
public List<String> getList() {
return list;
}
@Override
public ProtoObject clone() throws CloneNotSupportedException {
return (ProtoObject) super.clone();
}
public ProtoObject deepClone() {
ProtoObject protoObject = null;
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("protoObject"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("protoObject"))) {
oos.writeObject(this);
protoObject = (ProtoObject)ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return protoObject;
}
}
public class PrototypeDemo {
public static void main(String[] args) throws CloneNotSupportedException {
ProtoObject protoObject = new ProtoObject();
ProtoObject protoObjectCommon = protoObject.clone();
ProtoObject protoObjectDeep = protoObject.deepClone();
System.out.println("克隆后赋值原型对象list");
protoObject.getList().add("A");
System.out.println("原型对象:" + protoObject);
System.out.println("浅克隆结果:" + protoObjectCommon);
System.out.println("深克隆结果:" + protoObjectDeep);
}
}
运行结果:
克隆后赋值原型对象list
原型对象:ProtoObject(list=[A])
浅克隆结果:ProtoObject(list=[A])
深克隆结果:ProtoObject(list=[])
8、责任链模式
public abstract class AbstractChain {
private AbstractChain nextChain;
abstract void doSomethingBefore(String request);
abstract void doSomethingAfter(String request);
public void handler(String request) {
doSomethingBefore(request);
AbstractChain chain = getNextChain();
if (chain != null) {
chain.handler(request);
}
doSomethingAfter(request);
}
public AbstractChain getNextChain() {
return nextChain;
}
public void setNextChain(AbstractChain nextChain) {
this.nextChain = nextChain;
}
}
public class ConcreteHandlerA extends AbstractChain {
@Override
void doSomethingBefore(String request) {
System.out.println("ConcreteHandlerA doSomethingBefore " + request);
}
@Override
void doSomethingAfter(String request) {
System.out.println("ConcreteHandlerA doSomethingAfter " + request);
}
}
public class ConcreteHandlerB extends AbstractChain {
@Override
void doSomethingBefore(String request) {
System.out.println("ConcreteHandlerB doSomethingBefore " + request);
}
@Override
void doSomethingAfter(String request) {
System.out.println("ConcreteHandlerB doSomethingAfter " + request);
}
}
public class ConcreteHandlerC extends AbstractChain {
@Override
void doSomethingBefore(String request) {
System.out.println("ConcreteHandlerC doSomethingBefore " + request);
}
@Override
void doSomethingAfter(String request) {
System.out.println("ConcreteHandlerC doSomethingAfter " + request);
}
}
public class ChainDemo {
public static void main(String[] args) {
ConcreteHandlerA concreteHandlerA = new ConcreteHandlerA();
ConcreteHandlerB concreteHandlerB = new ConcreteHandlerB();
ConcreteHandlerC concreteHandlerC = new ConcreteHandlerC();
concreteHandlerA.setNextChain(concreteHandlerB);
concreteHandlerB.setNextChain(concreteHandlerC);
concreteHandlerA.handler("request");
}
}
运行结果:
ConcreteHandlerA doSomethingBefore request
ConcreteHandlerB doSomethingBefore request
ConcreteHandlerC doSomethingBefore request
ConcreteHandlerC doSomethingAfter request
ConcreteHandlerB doSomethingAfter request
ConcreteHandlerA doSomethingAfter request
9、委派模式
public interface IEmployee {
void doing(String task);
}
public class EmployeeA implements IEmployee {
protected String name;
public EmployeeA(String name){
this.name = name;
}
@Override
public void doing(String task) {
System.out.println("我是员工A,我擅长"+name+",现在开始做"+task+"工作");
}
}
public class EmployeeB implements IEmployee {
protected String name;
public EmployeeB(String name){
this.name = name;
}
@Override
public void doing(String task) {
System.out.println("我是员工B,我擅长"+name+",现在开始做"+task+"工作");
}
}
public class Leader implements IEmployee {
HashMap<String,IEmployee> map = new HashMap<>();
public Leader(){
map.put("登录",new EmployeeA("开发"));
map.put("登录页面",new EmployeeB("UI"));
}
@Override
public void doing(String task) {
map.get(task).doing(task);
}
}
public class DelegateDemo {
public static void main(String[] args) {
new Leader().doing("登录");
new Leader().doing("登录页面");
}
}
运行结果:
我是员工A,我擅长开发,现在开始做登录工作
我是员工B,我擅长UI,现在开始做登录页面工作
10、装饰器模式
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
}
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
public class DecoratorDemo {
public static void main(String[] args) {
Shape circle = new Circle();
ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
//Shape redCircle = new RedShapeDecorator(new Circle());
//Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
运行结果:
Circle with normal border
Shape: Circle
Circle of red border
Shape: Circle
Border Color: Red
Rectangle of red border
Shape: Rectangle
Border Color: Red
11、观察者模式
public class Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Binary String: " + Integer.toBinaryString(subject.getState()));
}
}
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: " + Integer.toOctalString(subject.getState()));
}
}
public class HexaObserver extends Observer{
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() );
}
}
public class ObserverDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}