15、简单工厂模式
由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
使用者和被使用者两者之间,耦合,产生了依赖,当被使用者改变时,会影响被使用者
使用工厂模式来降低两者之间的依赖
package objectoriented;
public class SimpleFactory {
public static void main(String[] args) {
// Product phone = new Phone();
// phone.work();
Product phone = ProductFactory.getProduct("phone");
phone.work();
Product computer = ProductFactory.getProduct("computer");
computer.work();
}
}
class ProductFactory {
public static Product getProduct(String name) {
if ("phone".equals(name))
return new Phone();
else if ("computer".equals(name)) {
return new Computer();
} else
return null;
}
}
interface Product {
public void work();
}
class Phone implements Product {
@Override
public void work() {
System.out.println("手机开始工作");
}
}
class Computer implements Product {
@Override
public void work() {
System.out.println("电脑开始工作");
}
}
16、 静态代理模式
代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问
就是 ”真实对象“ 的代表,在访问对象时引入一定程度的间接性,因为这种间接性可以附加多种用途
业务接口, 业务实现类, 代理对象
package objectoriented;
public class ProxyTest {
public static void main(String[] args){
Action userAction = new UserAction();
ActionProxy proxy = new ActionProxy(userAction);
proxy.doAction();
}
}
class ActionProxy implements Action{
private Action target;
public ActionProxy(Action target) {
this.target = target;
}
// 执行操作
@Override
public void doAction() {
long startTime = System.currentTimeMillis();
target.doAction();
long endTime = System.currentTimeMillis();
System.out.println("共耗时 "+(endTime - startTime));
}
}
interface Action{
public void doAction();
}
class UserAction implements Action{
@Override
public void doAction() {
System.out.println("用户开始工作");
}
}
一个动作的接口, 接口中有抽象方法
一个用户动作类实现了接口,实现了抽象方法
现在可以新建一个动作代理类,把用户动作嵌套在动作代理类里面,并实现抽象方法,方法中可以添加新的功能,并调用用户动作的方法。实现了增加用户方法功能的作用。
17、适配器模式
适配器模式(Adapter) :将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
OO设计原则:
面向接口编程(面向抽象编程)
封装变化
多用组合,少用继承
对修改关闭,对扩展开放
class test{ public static void main(String[] args){ PowerA powerA = new PowerAImpl(); work(powerA); PowerB powerB = new PowerBimpl(); Adapter adapter = new Adapter(powerB); work(adapter); } public static void work(PowerA a){ // 这个work 只接受PowerA的,PowerB的不行 // 所以以PowerA为基础,创建一个适配器,把powerB传到适配器中,work作用于适配器,适配器作用于powerB System.out.println("正在连接"); a.inset(); System.out.println("工作结束"); } } interface PowerA{ public void insert(); } class PowerAImpl implements PowerA{ public void insert(){ System.out.println("电源A开始工作"); } } interface PowerB{ public void connect(); } class PowerBImpl implements PowerB{ public void connect(){ System.out.println("电源B开始工作"); } } class Adapter implements PowerA{ private PowerB powerB; public Adapter(PowerB PowerB){ this.powerB = powerB; } public void insert(){ powerB.connect(); } }
18、内部类
就是在类中定义的类,编译后会产生两个文件 Outer.class Outer$Inner.class
在外部创建内部类对象
内部类除了可以在外部类中产生实例化对象,也可以咋外部类的外部来实例化
那么,根据内部类生成的*.class 文件: Outer$Inner.class
$ 符号在程序运行的时将被替换成 .
所以内部类的访问,通过外部类. 内部类 的形式表示
成员内部类和方法内部类的优势是能够使用外部类的成员变量和方法,集合中(源码)内部类用的比较多,内部类使得多重继承的解决方案变得更加完整
静态内部类只能访问外部类的静态成员变量和静态方法
package objectoriented;
public class InnerClass {
public static void main(String[] args){
// 使用Inner 成员内部类, 不建议这样在外部实例化内部类
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.print();
// 使用成员内部类实例化的方法
outer.innerPrint();
// 使用方法内部类
outer.show();
// 使用静态内部类
Outer.Inner3 inner3 = new Outer.Inner3();
inner3.print();
// 内部类 继承
outer.print1();
// 内部类 接口
outer.print2();
// 内部类 参数式
outer.print3(new Eat(){public void eat(){
System.out.println("参数式匿名内部类");
// System.out.println("参数式匿名内部类"+ name) 错误,参数式匿名内部类不能访问外部类的成员变量;
}});
}
}
class Outer{
private static String name = "hahaaha";
public void innerPrint(){
// 使用Inner 成员内部类
Inner inner = new Inner();
inner.print();
}
// 成员内部类, 可以在外部类之外使用成员内部类, 也可以在外部类的方法中new, innerPrint()方法中使用
public class Inner{
public void print(){
System.out.println("成员内部类" + name);
}
public Outer outer() {
return Outer.this; // key: 生成对外部类对象的引用.
}
}
// 方法内部类, 在外部类的方法中定义一个类,并在方法中new,所以调用这个方法,就可以调用内部类
// show方法的局部变量或方法的参数,实际必须是常量final, JDK1.8 中可以不加final,但默认final
public void show(){
/**final*/ int x = 10; // 可以访问, 但是能修改
class Inner2{
// x= x + 1; 出错
public void print(){
System.out.println("方法内部类" + x + name);
}
}
Inner2 inner2 = new Inner2();
inner2.print();
}
// 静态内部类, 没有外部类的对象时,也能访问他,只能访问外部类的静态成员变量和方法,静态内部类就像是外部类,能够直接实例化。
static class Inner3{
public void print(){
System.out.println("静态内部类"+ name);
}
}
// 匿名内部类
// 继承式
public void print1(){ // 不需要extends
Cat cat = new Cat(){
public void eat(){
System.out.println("cat: 继承式匿名内部类"+ name);
}
}; // 一定加分号,因为这是一个语句
cat.eat();
}
//接口式
public void print2(){ // 不需要 implements
Eat eat = new Eat(){
public void eat(){
System.out.println("eat:接口式匿名内部类"+ name);
}
};
}
//有参数的,这里是把接口传进入
public void print3(Eat eat){ // 不能使用name(外部类的成员变量)
eat.eat();
}
}
abstract class Cat{
public abstract void eat();
}
interface Eat{
void eat();
}
如何在任意的作用域内嵌入一个内部类
public class Parcel6 {
private void internalTracking(boolean b) {
if (b) {
class TrackingSlip { // if 条件语句中 定义 局部内部类
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() { return id; }
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
System.out.println(s);
}
// 在 定义 TrackingSlip 的作用域之外 创建 TrackingSlip 实例是不可行的.
// TrackingSlip instance = new TrackingSlip("str"); // syntax error.
}
public void track() {
internalTracking(true);
}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
p.track();
}
}
在接口中的静态内存类
interface ClassInInterface{
void howdy();
class Test implements ClassInInterface { // 默认是 public static
public void howdy() {
System.out.println("Howdy!");
}
public static void test() {
System.out.println("my name is test.");
}
public static void main(String[] args) {
new Test().howdy();
}
}
}
方法内部类
内部类可以作为一个类的成员外,还可以把类放在方法内定义
注意:
1、 方法内部类只能在定义该内部类的方法内实例化,不可以再此方法外对其实例化(有作用域的问题)
- 方法内部类对象不能使用该内部类所在方法的非final 局部变量( 从内部类引用的本地变量必须是最终变量或实际上的最终变量)
静态内部类
在一个类内部定义一个静态内部类
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法(无法访问外部的非静态)
匿名内部类
没有名字的内部类,三种情况:
- 继承式的匿名内部类
- 接口式的匿名内部类
- 参数式的匿名内部类
在使用匿名内部类时, 有以下几点原则
- 不能有构造方法,只能有一个实例
- 不能定义任何静态成员,静态方法
- 不能是public , protected, private, static
- 一定是在new 后面, 用其隐含实现一个接口或实现一个类
- 匿名内部类为局部的,所以局部内部类的所有限制对其生效
什么局方法内部类访问方法的局部变量必须用final 修饰?
当调用这个方法时,局部变量如果没有用final修饰, 他的生命周期和方法的生命周期是一样的,当方法被调用时就会入栈,方法结束后就会弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失,想用这个局部变量,显然已无法使用了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也就可以继续使用了。
注意: 在jdk1.8 中取消了在局部内部类中使用的变量必须显示的使用final 修饰, 编译器会认为这个变量已经加上了final, 如果尝试在程序中修改外部类的成员变量,那么会报错,内部类的成员变量也是不能修改的(没有final)
内部类的作用
每个内部类都能独立地继承自一个(接口)的实现,所以无论外部类是否已经继承了某个(接口)的实现,对于内部类没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案更加完整。接口解决了部分问题,而内部类有效地实现了”多重继承“。
静态内部类不依赖外部类的对象,所以我们在项目中优先考虑选择静态内部类(不会产生内存泄漏)
为什么需要内部类?
1)内部类最吸引人的原因: 每个内部类都能独立继承自一个(接口的)实现, 所以无论外围类是否已经继承了某个(接口的)实现, 对于内部类都没有影响;
2)内部类使得多重继承的解决方案变得完整。接口解决了多重继承的部分问题, 内部类有效地实现了 多重继承。也就是说, 内部类允许继承多个非接口类型(译注:类或抽象类);
编译原理
在编译时,内部子类会被编译成一个单独的类,外部类的成员变量会变为构造函数的参数传入内部类。
19、数据结构之链表
20、基本数据结构包装类
int char float double boolean byte short long
Integer Character Float Double Boolean Byte Short Long 椅子着框架是篇垃圾 培训 链接
Integer x1 = new Integer(10);
Integer x2 = new Integer(10);
System.out.println(x1 == x2);
System.out.println(x1.equals(x2));
Integer x3 = new Integer(128);
Integer x4 = new Integer(128);
System.out.println(x3 == x4);
System.out.println(x3.equals(x4));
Integer x5 = 10;
Integer x6 = 10;
System.out.println(x5 == x6);
System.out.println(x5.equals(x6));
Integer x7 = 128;
Integer x8 = 128;
System.out.println(x7 == x8);
System.out.println(x7.equals(x8));
21、包与访问修饰符
访问修饰符 | 同一个类 | 同一个包 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | |
默认 | Y | Y | ||
private | Y |