定义:使用对象封装一些变量和函数
作用:复用和信息隐藏,封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽象。抽象包括行为抽象和状态抽象两个方面。
定义:一个类获取另外一个类属性和方法的一种方式
作用:代码复用,继承,就是可以使用已创建好的类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
定义:同一个操作,作用于不用的对象,会有不同的行为
作用:具有可拓展性详解:多态首先是建立在继承的基础上的,先有继承才能有多态。多态是指不同的子类在继承父类后分别都重写覆盖了父类的方法,即父类同一个方法,在继承的子类中表现出不同的形式。js天生就具备多态的特性(弱类型语言)
原理:靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定
## AOP和OOP
OOP主要功能封装、继承、多态,AOP它是将系统分解为不同的关注点(不同的切面)。
OOP,我们会根据业务将应用划分为多个不同的业务模块,每个模块的核心功能只为某个核心业务提供服务,如学生宿舍管理系统,学生管理、班级管理、房间管理,分别学生、班级、房间服务的。
除此之外,还会有一些非业务的通用功能,如日志、权限、事务管理等。它们和业务无关,但是几乎所有的模块都会用到它。因此这些通用功能会散布在不同的业务模块中。此时会有很多重复性的代码,不理模块的复用。
为了解决这个问题,AOP(面向切面编程)就出来了,它是把非业务的通用功能抽取出来单独维护,并通过声明的方式(定义切入点)去指定这些功能以何种方式(通知类型)作用在哪里(方法连接点--目标方法),而不是直接在模块的代码中去直接添加。
3.4 默认是浮点double类型的,如果赋值给float是向下转型,会出现精度缺失,,需要强制转换
byte、short、int、char 、 enum 、 String
## 存储位置不同:
基本数据类型直接将值放在栈中;(非static的成员变量存在堆中)
包装类型是把对象放在堆中,然后通过对象的引用来调用他们 ;
## 初始值不同:
int的初始值为 0 、 boolean的初始值为false ;
包装类型的初始值为null ;
## 使用方式不同:
基本数据类型直接赋值使用就好;
在集合如 coolectionMap 中只能使用包装类型;包装类型可以使用在泛型中
## 手动转换
基本数据类型 → 包装类:
通过对应包装类的构造方法实现(Integer.valueOf(10)),除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。
包装类 → 基本数据类型
通过包装类的实例方法 xxxValue() 实现; // xxx表示包装类对应的基本数据类型
## 自动装箱&自动拆箱(jdk1.5以后)
基本类型添加到集合中时,进行自动装箱
包装类型在涉及到运算的时候,“加,减,乘, 除” 以及 “比较 equals,compareTo”,进行自动拆箱
Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean
直接返回 True
or False
。
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2); // 输出 False
引用数据类型 和 数组
## 引用数据类型的变量定义及赋值格式:
数据类型 变量名 = new 数据类型();
调用该类型实例的功能:变量名.方法名();
## 数组
一组数据的集合,数组中的每个数据被称作'元素'
在数组中可以存放'任意类型'的元素但'同一个数组'里存放的元素类型必须一致。
格式: int[] x = new int[100];
使用属性:数组名.length
构成:
注意:
可变参数:
public void sum(int... n){}
## 1、创建型模式
对象实例化的模式,创建型模式用于解耦对象的实例化过程。
单例模式:某个类智能有一个实例,提供一个全局的访问点。
工厂模式:一个工厂类根据传入的参量决定创建出哪一种产品类的实例。
抽象工厂模式:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的创建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
## 2、结构型模式
把类或对象结合在一起形成一个更大的结构。
装饰器模式:动态的给对象添加新的功能。
代理模式:为其它对象提供一个代理以便控制这个对象的访问。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
适配器模式:将一个类的方法接口转换成客户希望的另一个接口。
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
享元模式:通过共享技术来有效的支持大量细粒度的对象。
## 3、行为型模式
类和对象如何交互,及划分责任和算法。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
观察者模式:对象间的一对多的依赖关系。
仲裁者模式:用一个中介对象来封装一系列的对象交互。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
访问者模式:不改变数据结构的前提下,增加作用于一组对象元素的新功能。
设计模式是一组重复的经验,大多数人都知道,编目和代码设计经验。使用设计模式是重用代码,使代码更容易被其他人理解,并确保代码的可靠性。
单例模式就是在程序运行中只实例化一次,创建一个全局唯一对象。
饿汉模式:不能实现懒加载,造成空间浪费
//在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
public class SingletonObject {
// 利用静态变量来存储唯一实例
private static final SingletonObject instance = new SingletonObject();
// 私有化构造函数
private SingletonObject(){
// 里面可能有很多操作
}
// 提供公开获取实例接口
public static SingletonObject getInstance(){
return instance;
}
}
懒汉模式:
public class SingletonObject {
// 定义静态变量时,未初始化实例
private static SingletonObject instance;
// 私有化构造函数
private SingletonObject(){
}
public static SingletonObject getInstance(){
// 使用时,先判断实例是否为空,如果实例为空,则实例化对象
// 这段代码在多线程的情况下是不安全的
if (instance == null)
instance = new SingletonObject();
return instance;
}
}
静态内部类单例模式:静态内部类单例模式实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。
public class SingletonObject {
private SingletonObject(){
}
// 单例持有者
private static class InstanceHolder{
private final static SingletonObject instance = new SingletonObject();
}
//
public static SingletonObject getInstance(){
// 调用内部类属性
return InstanceHolder.instance;
}
}
枚举类单例模式:枚举类型是线程安全的,并且只会装载一次,而且枚举类型是所用单例实现中唯一一种不会被破坏的单例实现模式。
public class SingletonObject {
private SingletonObject(){
}
private enum Singleton{
INSTANCE;
private final SingletonObject instance;
Singleton(){
instance = new SingletonObject();
}
private SingletonObject getInstance(){
return instance;
}
}
public static SingletonObject getInstance(){
return Singleton.INSTANCE.getInstance();
}
}
除枚举方式外,其他方法都会通过反射的方式破坏单例,反射是通过调用构造方法生成新的对象,所以如果我们想要阻止单例破坏,可以在构造方法中进行判断,若已有实例, 则阻止生成新的实例。
private SingletonObject(){
if (instance !=null){
throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
}
}
如果单例类实现了序列化接口Serializable, 就可以通过反序列化破坏单例,所以我们可以不实现序列化接口,如果非得实现序列化接口,可以重写反序列化方法readResolve(), 反序列化时直接返回相关单例对象。
public Object readResolve() throws ObjectStreamException {
return instance;
}
椅子
接口;所有风格的咖啡桌都实现咖啡桌
接口,以此类推。create-Chair
创建椅子、create-Sofa
创建沙发和create-Coffee-Table
创建咖啡桌。这些方法必须返回抽象产品类型,即我们之前抽取的那些接口:椅子,沙发和咖啡桌等等。抽象工厂
接口创建不同的工厂类。每个工厂类都只能返回特定类别的产品,例如,现代家具工厂 Modern-Furniture-Factory 只能创建现代椅子 Modern-Chair 、现代沙发 Modern-Sofa 和现代咖啡桌Modern-Coffee-Table 对象。抽象产品(Abstract Product)为构成系列产品的一组不同但相关的产品声明接口。
具体产品(Concrete Product)是抽象产品的多种不同类型实现。所有变体(维多利亚/现代)都必须实现相应的抽象产品(椅子/沙发)。
抽象工厂(Abstract Factory)接口声明了一组创建各种抽象产品的方法。
具体工厂(Concrete Factory)实现抽象工厂的构建方法。每个具体工厂都对应特定产品变体,且仅创建此种产品变体。
装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
装饰器模式的主要优点有:
package decorator;
import java.awt.*;
import javax.swing.*;
public class MorriganAensland {
public static void main(String[] args) {
Morrigan m0 = new original();
m0.display();
Morrigan m1 = new Succubus(m0);
m1.display();
Morrigan m2 = new Girl(m0);
m2.display();
}
}
//抽象构件角色:莫莉卡
interface Morrigan {
public void display();
}
//具体构件角色:原身
class original extends JFrame implements Morrigan {
private static final long serialVersionUID = 1L;
private String t = "Morrigan0.jpg";
public original() {
super("《恶魔战士》中的莫莉卡·安斯兰");
}
public void setImage(String t) {
this.t = t;
}
public void display() {
this.setLayout(new FlowLayout());
JLabel l1 = new JLabel(new ImageIcon("src/decorator/" + t));
this.add(l1);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
//抽象装饰角色:变形
class Changer implements Morrigan {
Morrigan m;
public Changer(Morrigan m) {
this.m = m;
}
public void display() {
m.display();
}
}
//具体装饰角色:女妖
class Succubus extends Changer {
public Succubus(Morrigan m) {
super(m);
}
public void display() {
setChanger();
super.display();
}
public void setChanger() {
((original) super.m).setImage("Morrigan1.jpg");
}
}
//具体装饰角色:少女
class Girl extends Changer {
public Girl(Morrigan m) {
super(m);
}
public void display() {
setChanger();
super.display();
}
public void setChanger() {
((original) super.m).setImage("Morrigan2.jpg");
}
}
代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
静态代理:在编译时就已经实现,编译完成后代理类是一个实际的class文件。
创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。
动态代理:通过Proxy.getProxyClass
获得动态代理类;
通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)
;
通过构造函数获得代理对象并将自定义的InvocationHandler
实例对象传为参数传入;
类适配器:Adapter 类,通过继承 src 类,实现 dst 类接口,完成 src->dst 的适配。
// src
public class Voltage220V{
public int output220V() {
int src = 220;
System.out.println("电压:" + src);
return src;
}
}
// dst
public interface IVoltage5V {
int output5V();
}
// adapter
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
@Override
public int output5V() {
int srcV = output220V();
int dstV = srcV / 44;
return dstV;
}
}
//使用
public class Client {
public static void main(String[] args) {
System.out.println("适配器模式");
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
Java 是单继承机制,所以类适配器需要继承 src 类这一点算是一个缺点, 因为这要求 dst 必须是接口,有一定局限性;
src 类的方法在 Adapter 中都会暴露出来,也增加了使用的成本。
对象适配器:基本思路和类的适配器模式相同,只是将 Adapter 类作修改,不是继承 src 类,而是持有 src 类的实例,以解决兼容性的问题。 即:持有 src 类,实现 dst 类接口,完成 src->dst 的适配
public class Client {
public static void main(String[] args) {
System.out.println("适配器模式");
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
观察者模式是一种行为设计模式,指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 这种模式和发布-订阅模式很像,不同的是,发布-订阅模式,一般有一个调度中心,调度中心有拉模式和推模式来推送消息。
//抽象观察者
public interface Observer {
void response(); //反应
}
public class ConcreteStudentA implements Observer{
@Override
public void response() {
System.out.println("学生A,收起自己的零食");
}
}
//抽象主题,提供保存观察者的类,可以新增或移除观察者
public abstract class Subject {
protected List<Observer> observers = new ArrayList<Observer>();
//增加观察者方法
public void add(Observer observer) {
observers.add(observer);
}
//删除观察者方法
public void remove(Observer observer) {
observers.remove(observer);
}
public abstract void notifyObserver(); //通知观察者方法
}
//具体主题
public class ConcreteSubject extends Subject{
@Override
public void notifyObserver() {
System.out.println("被观察者看到班主任来了,喊了一句:老师来了!");
for (Object obs : observers) {
((Observer)obs).response(); //观察者做出反应
}
}
}
对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法.定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
思想:在运行时
(非编译时)改变软件的算法行为,定义一个通用的问题,使用不同的算法来实现,然后将这些算法都封装在一个统一接口。
Strategy bySubway = new BySubwayStrategy();
//乘地铁
Context ctx = new Context(bySubway);
ctx.goToPark();
//乘公交
Strategy byBus = new ByBusStrategy();
ctx.setStrategy(byBus);
ctx.goToPark();
应用:当有大量条件语句在同一算法的不同变体之间切换时,可将每个条件分支移入它们各自的策略类中替代这些条件语句,来消除这种条件。
在面向对象的开发中,往往力求对象之间保持松耦合,确保对象各自的责任最小化、具体化。经常用Filter做拦截器,即把所有的Filter都放在FilterChain中,然后依次执行每个过滤器,有符合条件的就处理,直到没有其他过滤器,就访问请求的资源。
public interface LeaderChain {
public abstract void setNextChain(LeaderChain nextChain);
public abstract void handleRequest(int days);
}
//组长
public class GroupLeader implements LeaderChain{
private LeaderChain nextChain;
//这部分可以提取BaseHandle
@Override
public void setNextChain(LeaderChain nextChain) {
this.nextChain=nextChain;
}
@Override
public void handleRequest(int days) {
if(1==days){
System.out.println("组长同意");
}else{
//交给上一级处理
this.nextChain.handleRequest(days);
}
}
}
//...部门经理,部门总监,总经理
public static void Leaveapplication(int days){
LeaderChain gl = new GroupLeader();
LeaderChain dp = new DpManager();
LeaderChain cf = new CfInspector();
LeaderChain gm = new GeneralManager();
gl.setNextChain(dp);
dp.setNextChain(cf);
cf.setNextChain(gm);
//提交请求
gl.handleRequest(days);
}
}
? 备忘录模式是一种行为设计模式,又叫快照模式,是指在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后需要时能将该对象恢复到原先保存的状态。具体采用哪种方法来存储对象状态,取决于对象需要保存时间的长短。
public class LolOriginator { // 发起者
public LolOriginator(String name,String type,Integer fightingNum){
this.name = name;
this.type = type;
this.fightingNum = fightingNum;
}
//创建一个备忘录,进行备忘操作
public LolMemento createMemento(){
return new LolMemento(this);
}
//恢复成指定备忘录
public void restoreMemento(LolMemento memento){
this.name = memento.getName();
this.type = memento.getType();
this.fightingNum = memento.getFightingNum();
}
}
//备忘录
public class LolMemento {
private String name; //英雄名字
private String type; //英雄类型
private Integer fightingNum; //英雄战斗力
public LolMemento(LolOriginator lol){
this.name=lol.getName();
this.type=lol.getType();
this.fightingNum = lol.getFightingNum();
}
}
//管理者,负责管理备忘录对象
public class LolCaretaker {
private LolMemento memento;
//如果有一连串的状态加成,可以保存多个状态
//private List<LolMemento> mementoList = new ArrayList<LolMemento>();
public LolMemento getMemento() {
return memento;
}
public void setMemento(LolMemento memento) {
this.memento = memento;
}
}
//使用
public static void main(String[] args) {
//备忘录管理者
LolCaretaker taker = new LolCaretaker();
//创建一个英雄
System.out.println("当前的英雄信息:");
LolOriginator lol = new LolOriginator("德玛西亚之力", "战士", 666);
System.out.println(" "+lol.toString());
//进行一次备忘
taker.setMemento(lol.createMemento());
System.out.println("吃了一个红buff:");
lol.setFightingNum(700);
System.out.println(" "+lol.toString());
System.out.println("红buff已经失效:");
lol.restoreMemento(taker.getMemento()); //恢复到之前的状态
}
}