菜贩
package com.shu;
/**
* @description: 蔬菜类
* @author: shu
* @createDate: 2022/9/10 17:35
* @version: 1.0
*/
public class VegVendor {
/**
* 供应
*/
public void supply(){
System.out.println("菜贩供应蔬菜给饭馆");
}
}
厨师
package com.shu;
/**
* @description: 厨房厨师
* @author: shu
* @createDate: 2022/9/10 17:36
* @version: 1.0
*/
public class Helper {
/**
* 烹饪菜
*/
public void cook(){
System.out.println("厨师正在烹饪菜");
}
}
服务员
package com.shu;
/**
* @description: 服务员
* @author: shu
* @createDate: 2022/9/10 17:38
* @version: 1.0
*/
public class Waiter {
/**
* 上菜
*/
public void service(){
System.out.println("服务员上菜");
}
}
清洁
package com.shu;
/**
* @description: 清洁工
* @author: shu
* @createDate: 2022/9/10 17:39
* @version: 1.0
*/
public class Clear {
public void clearRoom(){
System.out.println("清洁工打扫房间");
}
}
饭馆
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 17:40
* @version: 1.0
*/
public class RestaurantFace {
private VegVendor vegVendor;
private Helper helper;
private Waiter waiter;
private Clear clear;
public RestaurantFace() {
vegVendor=new VegVendor();
helper=new Helper();
waiter=new Waiter();
clear=new Clear();
}
/**
* 对外提供接口,完成一些复杂动作
*/
public void order(){
vegVendor.supply();
helper.cook();
waiter.service();
clear.clearRoom();
}
}
测试
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/10 17:42
* @version: 1.0
*/
public class Client {
public static void main(String[] args) {
RestaurantFace face = new RestaurantFace();
face.order();
}
}
外观门面类内部封装了大量的子系统资源,如蔬菜商、厨师、服务员、洗碗工,并于构造方法中依次对各个子系统进行了初始化操作,也就是说餐厅在开门前需要提前准备好这些资源,进行依次调度。
由上面的类图可以看出,client只需要调用Configuration的newMetaObject(Object object)方法就可以得到一个MetaObject对象,而具体的对象是怎么生成与client无关,下面我们可以看一下Configuration的部分源码分析。
//Configuration 类:
public class Configuration {
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
protected ObjectFactory objectFactory = new DefaultObjectFactory();
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
//MetaObject类
public class MetaObject {
private Object originalObject;
private ObjectWrapper objectWrapper;
private ObjectFactory objectFactory;
private ObjectWrapperFactory objectWrapperFactory;
private ReflectorFactory reflectorFactory;
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
}
优点
缺点
java的集合类-HashMap
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
private static final long serialVersionUID = 362498820763181265L;
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
/**
* Copies all of the mappings from the specified map to this map.
* These mappings will replace any mappings that this map had for
* any of the keys currently in the specified map.
*
* @param m mappings to be stored in this map
* @throws NullPointerException if the specified map is null
*/
public void putAll(Map<? extends K, ? extends V> m) {
putMapEntries(m, true);
}
}
人们总是惊叹女生们魔法师一般的化妆技巧,可以从素面朝天变成花容月貌(如图9-2所示),化妆前后简直判若两人,这正是装饰器的粉饰效果在发挥作用。
化妆接口
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 11:46
* @version: 1.0
*/
public interface Showable {
// 展示
public void show();
}
素颜
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 11:47
* @version: 1.0
*/
public class Girl implements Showable{
@Override
public void show() {
System.out.println("女生的素颜");
}
}
抽象类
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 11:48
* @version: 1.0
*/
public abstract class Decorator implements Showable{
private Showable showable;
public Decorator(Showable showable) {
this.showable = showable;
}
@Override
public void show() {
showable.show();
}
}
粉底
package com.shu;
/**
* @description: 粉底
* @author: shu
* @createDate: 2022/9/11 12:06
* @version: 1.0
*/
public class FoundationMakeup extends Decorator {
public FoundationMakeup(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.println("打粉底了");
super.show();
}
}
口红
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 12:07
* @version: 1.0
*/
public class Lipstick extends Decorator{
public Lipstick(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.println("涂口红");
super.show();
}
}
测试
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 11:49
* @version: 1.0
*/
public class Client {
public static void main(String[] args) {
new Lipstick(new FoundationMakeup(new Girl())).show();
}
}
优点
缺点
java.io中的使用
在Java开发工具包(Java Development Kit,JDK)里就有大量应用,例如“java.io”包里一系列的流处理类InputStream、FileInputStream、BufferedInputStream、ZipInputStream等。
InputStream inputStream = new BufferedInputStream(new FileInputStream(""));
三相接口
package com.shu;
/**
* @description: 三相插孔接口
* @author: shu
* @createDate: 2022/9/11 17:30
* @version: 1.0
*/
public interface TriplePin {
/**
* 参数分别为火线,零线,地线
* @param l
* @param n
* @param e
*/
void electrify(int l,int n, int e);
}
两相插孔接口
package com.shu;
/**
* @description: 两相插孔接口
* @author: shu
* @createDate: 2022/9/11 17:33
* @version: 1.0
*/
public interface DualPin {
/**
* 参数分别为零线与火线
* @param l
* @param n
*/
void electrify(int l,int n);
}
电视
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 17:35
* @version: 1.0
*/
public class TV implements DualPin{
/**
* 参数分别为火线,零线
*
* @param l
* @param n
*/
@Override
public void electrify(int l, int n) {
System.out.println("接通火线,零线");
System.out.println("电视开机");
}
}
测试
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 17:37
* @version: 1.0
*/
public class Client {
public static void main(String[] args) {
// 接口不兼容
TriplePin triplePin= new TV();
}
}
修改创建适配器
package com.shu;
/**
* @description: 插座适配器
* @author: shu
* @createDate: 2022/9/11 17:40
* @version: 1.0
*/
public class Adapter implements TriplePin{
private DualPin dualPin;
public Adapter(DualPin dualPin) {
this.dualPin = dualPin;
}
/**
* 参数分别为火线,零线,地线
*
* @param l
* @param n
* @param e
*/
@Override
public void electrify(int l, int n, int e) {
dualPin.electrify(l, n);
}
}
测试
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 17:37
* @version: 1.0
*/
public class Client {
public static void main(String[] args) {
DualPin dualPin = new TV();
Adapter adapter = new Adapter(dualPin);
adapter.electrify(1,0,-1);
}
}
最后,我们直接调用三插通电方法给电视机供电,表面上看我们使用的是三插通电标准,而实际上是用两插标准为电视机供电(只使用了火线与零线),最终电视机顺利开启,两插标准的电视机与三相插孔接口成功得以适配。
优点
缺点
Mbatis 日志收集分析
日志接口
public interface Log {
boolean isDebugEnabled();
boolean isTraceEnabled();
void error(String s, Throwable e);
void error(String s);
void debug(String s);
void trace(String s);
void warn(String s);
}
实现类
public class Log4jImpl implements Log {
private static final String FQCN = Log4jImpl.class.getName();
private final Logger log;
public Log4jImpl(String clazz) {
log = Logger.getLogger(clazz);
}
@Override
public boolean isDebugEnabled() {
return log.isDebugEnabled();
}
@Override
public boolean isTraceEnabled() {
return log.isTraceEnabled();
}
@Override
public void error(String s, Throwable e) {
log.log(FQCN, Level.ERROR, s, e);
}
@Override
public void error(String s) {
log.log(FQCN, Level.ERROR, s, null);
}
@Override
public void debug(String s) {
log.log(FQCN, Level.DEBUG, s, null);
}
@Override
public void trace(String s) {
log.log(FQCN, Level.TRACE, s, null);
}
@Override
public void warn(String s) {
log.log(FQCN, Level.WARN, s, null);
}
}
我们利用享元模式,加载游戏中的地图
绘图接口
package com.shu;
/**
* @description: 绘图接口
* @author: shu
* @createDate: 2022/9/11 18:15
* @version: 1.0
*/
public interface Drawable {
/**
* 绘制坐标
* @param x
* @param y
*/
void draw(int x,int y);
}
分别绘制河流,草地,道路,房屋
package com.shu;
/**
* @description: 河流地图
* @author: shu
* @createDate: 2022/9/11 18:16
* @version: 1.0
*/
public class River implements Drawable{
private String images;
public River() {
this.images = "河流";
System.out.println("从磁盘加载......");
}
/**
* 绘制坐标
*
* @param x
* @param y
*/
@Override
public void draw(int x, int y) {
System.out.println("在坐标:"+x+" "+y+"绘制"+images);
}
}
package com.shu;
/**
* @description: 草地地图
* @author: shu
* @createDate: 2022/9/11 18:22
* @version: 1.0
*/
public class Grass implements Drawable{
private String images;
public Grass() {
this.images = "草地";
System.out.println("从磁盘加载......");
}
/**
* 绘制坐标
*
* @param x
* @param y
*/
@Override
public void draw(int x, int y) {
System.out.println("在坐标:"+x+" "+y+"绘制"+images);
}
}
package com.shu;
/**
* @description: 道路
* @author: shu
* @createDate: 2022/9/11 18:23
* @version: 1.0
*/
public class Road implements Drawable{
private String images;
public Road() {
this.images = "道路";
System.out.println("从磁盘加载......");
}
/**
* 绘制坐标
*
* @param x
* @param y
*/
@Override
public void draw(int x, int y) {
System.out.println("在坐标:"+x+" "+y+"绘制"+images);
}
}
package com.shu;
/**
* @description: 房屋地图
* @author: shu
* @createDate: 2022/9/11 18:25
* @version: 1.0
*/
public class House implements Drawable{
private String images;
public House() {
this.images = "房屋";
System.out.println("从磁盘加载......");
}
/**
* 绘制坐标
*
* @param x
* @param y
*/
@Override
public void draw(int x, int y) {
}
}
地图工厂
package com.shu;
/**
* @description: 地图工厂
* @author: shu
* @createDate: 2022/9/11 18:26
* @version: 1.0
*/
import java.util.HashMap;
import java.util.Map;
public class TileFactory {
private Map<String, Drawable> images;//图库
public TileFactory() {
images = new HashMap<String, Drawable>();
}
public Drawable getDrawable(String image) {
//缓存池里如果没有图件,则实例化并放入缓存池
if (!images.containsKey(image)) {
switch (image) {
case "河流":
images.put(image, new River());
break;
case "草地":
images.put(image, new Grass());
break;
case "道路":
images.put(image, new Road());
break;
case "房屋":
images.put(image, new House());
}
}
//至此,缓存池里必然有图件,直接取得并返回
return images.get(image);
}
}
测试
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/11 18:27
* @version: 1.0
*/
public class Client {
public static void main(String[] args) {
//先实例化图件工厂
TileFactory factory = new TileFactory();
//随便绘制一列为例
factory.getDrawable("河流").draw(10, 10);
factory.getDrawable("河流").draw(10, 20);
factory.getDrawable("道路").draw(10, 30);
factory.getDrawable("草地").draw(10, 40);
factory.getDrawable("草地").draw(10, 50);
factory.getDrawable("草地").draw(10, 60);
factory.getDrawable("草地").draw(10, 70);
factory.getDrawable("草地").draw(10, 80);
factory.getDrawable("道路").draw(10, 90);
factory.getDrawable("道路").draw(10, 100);
//绘制完地板后接着在顶层绘制房屋
factory.getDrawable("房屋").draw(10, 10);
factory.getDrawable("房屋").draw(10, 50);
}
}
我们抛弃了利用“new”关键字随意制造对象的方法,改用这个图件工厂类来构建并共享图件元,外部需要什么图件直接向图件工厂索要即可。此外,图件工厂类返回的图件实例也不再包含坐标信息这个属性了,而是将其作为绘图方法的参数即时传入。
优点
缺点
平常在使用Integer类的时候。你是否思考过用valueOf还是用new创建Integer对象。看完源码就会发现在valueOf这个方法中它会先判断传进去的值是否在IntegerCache中,如果不在就创建新的对象,在就直接返回缓存池里的对象。这个valueOf方法就用到享元模式。它将-128到127的Integer对象先在缓存池里创建好,等我们需要的时候直接返回即可。所以在-128到127中的数值我们用valueOf创建会比new更快。如果你还想继续往里钻研,可以去看看IntegerCache如何实现。(面试题)
public final class Integer extends Number implements Comparable<Integer> {
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private final int value;
public Integer(int value) {
this.value = value;
}
}
package com.shu;
/**
* @description: 上网接口
* @author: shu
* @createDate: 2022/9/17 14:19
* @version: 1.0
*/
public interface Internet {
/**
* 连通上网
* @param url
*/
void httpAccess(String url);
}
package com.shu;
/**
* @description: 真正上网的对象
* @author: shu
* @createDate: 2022/9/17 14:21
* @version: 1.0
*/
public class Model implements Internet{
public Model(String passWord) throws Exception {
if(!"123456".equals(passWord)){
throw new Exception("密码错误!!!");
}
System.out.println("拨号成功!!!");
}
/**
* 连通上网
*
* @param url
*/
@Override
public void httpAccess(String url) {
System.out.println("正在上网"+url);
}
}
package com.shu;
/**
* @description: 代理对象
* @author: shu
* @createDate: 2022/9/17 14:25
* @version: 1.0
*/
import java.util.Arrays;
import java.util.List;
public class RouterProxy implements Internet {
private Internet modem;//被代理对象
private List<String> blackList = Arrays.asList("电影", "游戏", "音乐", "小说");
public RouterProxy() throws Exception {
this.modem = new Model("123456");//实例化被代理类
}
@Override
public void httpAccess(String url) {//实现互联网访问接口方法
for (String keyword : blackList) {//遍历黑名单
if (url.contains(keyword)) {//是否包含黑名单中的字眼
System.out.println("禁止访问:" + url);
return;
}
}
modem.httpAccess(url);//转发请求至“猫”以访问互联网
}
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:27
* @version: 1.0
*/
public class Client {
public static void main(String[] args) throws Exception {
Internet proxy = new RouterProxy();//实例化的是代理
proxy.httpAccess("http://www.电影.com");
proxy.httpAccess("http://www.游戏.com");
proxy.httpAccess("ftp://www.学习.com/java");
proxy.httpAccess("http://www.工作.com");
}
}
记住重要的一点,为其他对象提供一个代理以控制对某个对象的访问。代理类主要负责为委托了(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。
在我们的现实生活中其实有很多这样的案例,不如商品经销商与厂家的关系,出租房的人与中介。
package com.shu.agency;
/**
* @author shu
* @version 1.0
* @date 2022/7/20 16:00
* @describe 代理类和委托代理类都要实现的接口
*/
public interface Sell {
/**
* 销售产品
*/
void market();
/**
* 生成产品
*/
void add();
}
package com.shu.agency;
/**
* @author shu
* @version 1.0
* @date 2022/7/20 16:03
* @describe 生产厂家
*/
public class Production implements Sell{
@Override
public void market() {
System.out.println("生产厂家销售产品了哦!!!");
}
@Override
public void add() {
System.out.println("生产厂家销售产品了哦!!!");
}
}
package com.shu.agency;
/**
* @author shu
* @version 1.0
* @date 2022/7/20 16:05
* @describe 商家代销产品
*/
public class Merchant implements Sell{
Sell production;
public Merchant(Production production) {
this.production = production;
}
@Override
public void market() {
production.market();
}
@Override
public void add() {
production.add();
}
}
/**
* 调用处理程序
*/
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args);
}
定义中介类
package com.shu.agency;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author shu
* @version 1.0
* @date 2022/7/20 19:33
* @describe
*/
public class DynamicProxy implements InvocationHandler {
//obj为委托类对象;
private Object obj;
public DynamicProxy(Object obj) {
this.obj = obj;
}
/**
* 通过反射来执行真正的方法
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(obj, args);
return result;
}
}
测试
package com.shu.agency;
import java.lang.reflect.Proxy;
/**
* @author shu
* @version 1.0
* @date 2022/7/20 19:35
* @describe
*/
public class ProxyTest {
public static void main(String[] args) {
//创建中介类实例
DynamicProxy inter = new DynamicProxy(new Production());
//加上这句将会产生一个$Proxy0.class文件,这个文件即为动态生成的代理类文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
//获取代理类实例sell
Sell sell = (Sell)(Proxy.newProxyInstance(Sell.class.getClassLoader(), new Class[] {Sell.class}, inter));
sell.market();
sell.add();
}
}
优点
缺点
package com.shu;
/**
* @description: 画笔
* @author: shu
* @createDate: 2022/9/17 14:51
* @version: 1.0
*/
public abstract class Pen {
protected Ruler ruler;
public Pen(Ruler ruler) {
this.ruler = ruler;
}
public abstract void draw();
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:54
* @version: 1.0
*/
public interface Ruler {
/**
* 规则
*/
public void regularize();
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:52
* @version: 1.0
*/
public class BlackPen extends Pen{
public BlackPen(Ruler ruler) {
super(ruler);
}
@Override
public void draw() {
System.out.println("黑");
ruler.regularize();
}
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:58
* @version: 1.0
*/
public class WhitePen extends Pen {
public WhitePen(Ruler ruler) {
super(ruler);
}
@Override
public void draw() {
System.out.println("白");
ruler.regularize();
}
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:57
* @version: 1.0
*/
public class CircleRuler implements Ruler{
/**
* 规则
*/
@Override
public void regularize() {
System.out.println("圆形");
}
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:56
* @version: 1.0
*/
public class SquareRuler implements Ruler{
/**
* 规则
*/
@Override
public void regularize() {
System.out.println("正方形");
}
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:56
* @version: 1.0
*/
public class TriangleRuler implements Ruler{
/**
* 规则
*/
@Override
public void regularize() {
System.out.println("三角形");
}
}
package com.shu;
/**
* @description:
* @author: shu
* @createDate: 2022/9/17 14:59
* @version: 1.0
*/
public class Client {
public static void main(String args[]) {
//白色画笔对应的所有形状
new WhitePen(new CircleRuler()).draw();
new WhitePen(new SquareRuler()).draw();
new WhitePen(new TriangleRuler()).draw();
//黑色画笔对应的所有形状
new BlackPen(new CircleRuler()).draw();
new BlackPen(new SquareRuler()).draw();
new BlackPen(new TriangleRuler()).draw();
}
}
优点
缺点