聊一聊设计模式(三)-- 结构型设计模式
2020-02-05 本文已影响0人
ClericYi
![](https://img.haomeiwen.com/i13119381/6f175a24047b21b1.png)
前言
憋在家里的第8天,今天开始进入结构型设计模式。
思维导图
![](https://img.haomeiwen.com/i13119381/f12febfde99ece00.png)
结构型设计模式是从程序的结构上解决模块之间的耦合问题。
代理模式
定义:为其他对象提供一种代理以控制对这个对象的访问。
![](https://img.haomeiwen.com/i13119381/569d2f920e63db0e.png)
这个模式的几个角色分为以下:
- Subject:抽象主题类。
- RealSubject:真实主题类,客户端由Proxy来间接调用。
- Proxy:代理类
这个模式就像你和代购的存在一样,你提出需求,由代购来帮你购买。这个句子里基本上就概括了整个代理模式的全貌。客户端就是我们需求者,而真实主题就是你要找的代购帮你买,最后一个代理,找谁买。
以下用代码表示静态代理。
/**
* 抽象主题类
* 中心主题,买东西。
*/
public interface Shop {
void buy();
}
/**
* 真实主题类
* 有这么一个人,可以干这件事,他就是代理
*/
public class Person implements Shop {
@Override
public void buy() {
System.out.println("购买");
}
}
/**
* 代理类
* 你要告诉自己找那个代购买
*/
public class WhoBuy implements Shop {
private Shop shop;
WhoBuy(Shop shop){
this.shop = shop;
}
@Override
public void buy() {
shop.buy();
}
}
/**
* 客户端类
* 就是这个想买东西的人了
*/
public class User {
public static void main(String[] args) {
Shop person = new Person();
Shop purchase = new WhoBuy(person);
purchase.buy();
}
}
静态代理,主要是为了让人更好的理解代理模式。在开发中主要还是使用反射机制来完成的,也就是动态代理模式。
/**
* 动态代理类
*/
public class DynamicPurchase implements InvocationHandler {
private Object object;
DynamicPurchase(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);
if(method.getName().equals("buy")){
System.out.println("买上");
}
return result;
}
}
/**
* 客户端类
*/
public class User {
public static void main(String[] args) {
Shop person = new Person();
DynamicPurchase dynamicPurchase = new DynamicPurchase(person);
ClassLoader loader = person.getClass().getClassLoader();
Shop purchase = (Shop) Proxy.newProxyInstance(loader, new Class[]{Shop.class}, dynamicPurchase);
purchase.buy();
}
}
和静态代理的不同就在于代理类,使用反射机制。
这种代理模式的优点:
- 真实主题类只关注本身的业务逻辑。
- 真实主题类和代理类实现了公共接口,不必担心主题类的修改影响代理类。
装饰模式
动态地给一个对象添加一些额外的职责。
![](https://img.haomeiwen.com/i13119381/af8f296e11c417bc.png)
这个模式的角色有:
- Component:抽象组件。
- ConcreteComponent:组件具体实现类。
- Decorator:抽象装饰者,用于增加Component类的功能。
- ConcreteDecorator:装饰者的具体实现
人是一个慢慢学习的生物,从一开始只会咿咿呀呀,经过学习,学会了数学,英语。这个时候数学、英语,两个科目就是一种装饰了。
/**
* 抽象组件
* 作为一个人,必然会有学习的能力。
*/
public abstract class Person {
public abstract void learn();
}
/**
* 组件具体实现类
* 人一开始只会咿咿呀呀
*/
public class Me extends Person {
@Override
public void learn() {
System.out.println("咿咿呀呀");
}
}
/**
* 抽象装饰类
* 有一个老师教书育人
*/
public abstract class Teacher extends Person {
private Person person;
Teacher(Person person){
this.person = person;
}
@Override
public void learn() {
person.learn();
}
}
/**
* 装饰具体类
* 这个老师教数学,也就教会了孩子
*/
public class MathTeacher extends Teacher {
MathTeacher(Person person) {
super(person);
}
public void teach(){
System.out.println("学会了数学");
}
@Override
public void learn() {
super.learn();
teach();
}
}
// 具体使用
public class Main {
public static void main(String[] args) {
Person person = new Me();
MathTeacher mathTeacher = new MathTeacher(person);
mathTeacher.learn();
}
}
优点:
- 能够动态的为对象增加功能。
- 装饰类和组件类互不干扰。
缺点: - 不论是装饰类,还是组件类都继承自
Component
,如果Component
发生了改变,子类必然收到巨大的冲击。 - 装饰层数不宜过多,不仅影响效率,排查也比较苦难。
外观模式
要求一个子系统 的外部与内部的通信必须通过一个统一的对象进行。
![](https://img.haomeiwen.com/i13119381/555002c060538258.png)
这个模式的角色有:
- Facade:外观类
- Subsystem:子系统类
这里觉得之前看到的武侠的例子非常好。
一个武侠本身分为招式、内功、经脉三个系统,每次放招都是根据三个子系统的合理使用来释放。
/**
* 三大子系统
*/
public class 经脉 {
public void jingmai(){
System.out.println("开启经脉");
}
}
public class 内功 {
public void JiuYang(){
System.out.println("使用九阳神功");
}
public void QianKun(){
System.out.println("使用乾坤大挪移");
}
}
public class 招式 {
public void QiShangQuan(){
System.out.println("使用七伤拳");
}
public void ShengHuoLing(){
System.out.println("使用圣火令");
}
}
/**
* 外观类
* 也就是张无忌
*/
public class 张无忌 {
private JingMai jingMai;
private NeiGong neiGong;
private ZhaoShi zhaoShi;
张无忌(){
jingMai = new JingMai();
neiGong = new NeiGong();
zhaoShi = new ZhaoShi();
}
public void QianKun(){
jingMai.jingmai();
neiGong.QianKun();
}
public void QiShang(){
jingMai.jingmai();
neiGong.JiuYang();
zhaoShi.QiShangQuan();
}
}
给外人看到的只有张无忌的出招是七伤拳,但是不知道内部的具体操作,这也就是外观类的整体展现方式了。
优点:
- 所有的依赖都是出现在外观类的,子系统间互不干扰。
- 具体实现对用户隐藏,也就是用户和子系统处于松耦合状态,同时保障了子系统的安全性。
缺点:业务一旦出现变更,就需要直接修改外观类。
享元模式
使用共享对象有效地支持大量细粒度的对象。
![](https://img.haomeiwen.com/i13119381/b0541a00162895ff.png)
该模式下的对象有
- Flyweight:抽象享元角色。
- ConcreteFlyweight:具体享元角色
- FlyweightFactory:享元工厂,负责对象创建和管理。
其实往简单了说就是一种缓冲池的技术。
/**
* 享元工厂
*/
public class VipFactory {
private static Map<String, Vip> cache = new HashMap<>();
public static Vip getVip(String number){
if(cache.containsKey(number)){
return cache.get(number);
}else{
Vip vip = new Vip(number);
cache.put(number, vip);
return vip;
}
}
}
/**
* 享元角色
*/
public class Vip implements IVip {
private String name;
private String number;
Vip(String number){
this.number = number;
}
@Override
public void showVip(String number) {
if (number.equals(number)) {
System.out.println(name == null? "空": name);
}
}
}
/**
* 享元抽象角色
*/
public interface IVip {
void showVip(String number);
}
在享元工厂中我们显而易见的看到了由static
修饰的cache
变量,这就是一个缓冲,如果缓冲中存在,就从缓冲中取,不存在则创建。
以上就是我的学习成果,如果有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。
相关文章推荐:
聊一聊设计模式(一)-- 六大原则
聊一聊设计模式(二)-- 创建型设计模式
聊一聊设计模式(四)-- 行为型设计模式