组合模式
基本介绍
- 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。
- 组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
- 这种类型的设计模式属于结构型模式。
- 组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客
户以一致的方式处理个别对象以及组合对象
解决的问题
- 组合模式解决这样的问题,当我们的要处理的对象可以生成一颗树形结构,而我们要对树上的节点和叶子进行操作时,它能够提供一致的方式,而不用考虑它是节点还是叶子
- 对应的示意图
实例演示
分析
1)UML类图
2)创建父类
/*
* 定义一个基本的组件,不管它其中还包含了什么首先它都是电脑的组件
* */
public abstract class OriginalComponent {
private String name;
private String brand;
public OriginalComponent(String name, String brand) {
this.name = name;
this.brand = brand;
}
/*
* 我们先以最小组件的角度来看,它可以有哪些方法,其他如CPU这些
* 也是一个类,但是当它们继承的这个父类的时候,这些方法的使用具体
* 还要看它们的重写。在父类中默认我们的实现是抛出异常,也就是说
* 如果继承的类不重写这个方法,那么就是没有使用这个方法的权限。
* */
protected void add(OriginalComponent originalComponent){
throw new UnsupportedOperationException();
}
protected void remove(OriginalComponent originalComponent){
throw new UnsupportedOperationException();
}
/*
* 输出组件的信息是基本的功能,应该是每一个组件都有的,那么我们就将这个
* 方法定义为抽象的,每一个继承父类的子类都要实现这个方法。
* */
protected abstract void print();
}
3)根节点
/*
* 机箱内部也含有其他组件
* */
public class ComputerCase extends OriginalComponent{
List<OriginalComponent> componentList = new ArrayList<>();
public ComputerCase(String name, String brand) {
super(name, brand);
}
@Override
protected void add(OriginalComponent originalComponent) {
componentList.add(originalComponent);
}
@Override
protected void remove(OriginalComponent originalComponent) {
componentList.remove(originalComponent);
}
@Override
protected void print() {
for (OriginalComponent originalComponent : componentList) {
System.out.println("---机箱---");
originalComponent.print();
}
}
}
4)叶子结点
public class CPU extends OriginalComponent{
public CPU(String name, String brand) {
super(name, brand);
}
@Override
protected void print() {
System.out.println("部件名称:"+this.getName()+"\t 部件品牌"+getBrand());
}
}
5)组合
public class Client {
public static void main(String[] args) {
Computer computer = new Computer("电脑", "pox");
ComputerCase computerCase = new ComputerCase("机箱", "pox");
ComputerMotherboard computerMotherboard = new ComputerMotherboard("主板", "pox");
ComputerKeyboard computerKeyboard = new ComputerKeyboard("键盘", "pox");
Memory memory = new Memory("内存条", "pox");
Application application = new Application("应用", "pox");
Game game = new Game("绝地求生", "蓝洞");
computer.add(computerCase);
computer.add(computerKeyboard);
computerCase.add(computerMotherboard);
computerMotherboard.add(memory);
computer.add(application);
application.add(game);
computer.print();
}
}
6)测试
public class Game extends OriginalComponent{
public Game(String name, String brand) {
super(name, brand);
}
@Override
protected void print() {
System.out.println("游戏名称:"+this.getName()+"\t 游戏公司: "+getBrand());
System.out.println("安装完毕~~");
System.out.println("启动游戏....进入战场");
}
}
小结
补充
=====HashMap部分源码,关于put======
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
=====调用putVal方法存放=====
// 部分源码
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
// 存放到Node中
Node<K,V>[] tab; Node<K,V> p; int n, i;
}
代理模式
基本介绍
- 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
- 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
- 代理模式有不同的形式, 主要有三种 静态代理、动态代理 (JDK代理、接口代理)和 Cglib代理 (可以在内存动态的创建对象,而不需要实现接口, 他是属于动态代理的范畴) 。
静态代理
实例演示
1)UML类图
2)创建公共接口
public interface SellTickets {
void sell();
// 这里getname是为了后续分辨票的类型
String getName();
}
3)创建实现类
public class AirTickets implements SellTickets{
private String name = "Air";
@Override
public void sell() {
System.out.println("售卖飞机票~~");
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4)编写动态代理类
public class GoWhereProxy implements SellTickets{
SellTickets sellTickets;
private String name;
public GoWhereProxy(SellTickets sellTickets) {
name = "去哪儿";
this.sellTickets = sellTickets;
}
/*
* 这里可以根据传入的票的类型,做出相应的功能
* */
@Override
public void sell() {
if (sellTickets.getName().equals("Air")){
System.out.println("飞机票收取5%手续费");
sellTickets.sell();
System.out.println("出票~~");
} else if (sellTickets.getName().equals("Bus")){
System.out.println("汽车票收取1%手续费");
sellTickets.sell();
System.out.println("出票~~");
} else if (sellTickets.getName().equals("Train")){
System.out.println("火车票收取3%手续费");
sellTickets.sell();
System.out.println("出票~~");
}
}
@Override
public String getName() {
return name;
}
}
5)测试
public class Client {
public static void main(String[] args) {
AirTickets airTickets = new AirTickets();
BusTicket busTicket = new BusTicket();
TrainTicket trainTicket = new TrainTicket();
/*
* 开设三个窗口,每个窗口售卖指定类型的票
* 分别代理飞机、汽车、火车
* */
GoWhereProxy goWhereProxy1 = new GoWhereProxy(airTickets);
goWhereProxy1.sell();
GoWhereProxy goWhereProxy = new GoWhereProxy(busTicket);
goWhereProxy.sell();
GoWhereProxy goWhereProxy2 = new GoWhereProxy(trainTicket);
goWhereProxy2.sell();
}
}
6)结果
小结
优点:在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展
缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类
一旦接口增加方法,目标对象与代理对象都要维护
动态代理
基本介绍
- 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
- 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象
- 动态代理也叫做:JDK代理、接口代理
实例测试
1)UML类图
2)创建公共接口
public interface SellTickets {
void sell();
}
3)实现公共接口
public class AirTicket implements SellTickets{
@Override
public void sell() {
System.out.println("售卖飞机票~~");
}
}
4)编写动态代理
public class DynamicProxy {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
/*
* 这里是在获取动态代理类,这个动态代理类会根据,传入的类的类型来进行代理
* 就可以通过这里将票的类型不同而不同代理方式
* 这里的判断条件就是通过类的反射来获取到类的名称。通过类的名字不同,就可以判断
* 是不同的票的类型。
* */
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理模式开始~~");
/*
* target.getClass().getName().equals("dynamicproxy.AirTicket")就可以进行判断来做出不同的代理
* 为什么是:dynamicproxy.AirTicket,这个其实可以通过在控制台来打印获取到名称,这里我就是通过
* System.out.println(target.getClass().getName());来在控制台输出获取到类的名称的
* */
/*
* 11.30改进
* - 将获取类的信息改为instance判断
* */
if (target instanceof AirTicket){
System.out.println("收取5%的手续费");
} else if (target instanceof TrainTicket){
System.out.println("收取3%手续费");
} else if (target instanceof BusTicket){
System.out.println("收取1%手续费");
} else {
System.out.println();
}
Object invoke = method.invoke(target, args);
System.out.println("出票~~");
return invoke;
}
});
}
}