黑马程序员——第十章 设计模式
2015-05-13 14:30
218 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
1. 工厂模式
(1)简单工厂模式
原来需要我们自己去创建对象,现在不需要我们创建,只需要找工厂要就可以了Animal
|-Dog
|-Cat
|-Pig
AnimalFactory
publicstatic Animal createAnimal
代码体现
/** 顶层父类Animal,所有Animal都有eat()这个方法
*/
public
abstract class Animal {
public
abstract void eat();
}
/*****************************************************/
/*
* Cat类继承自Animal父类重写eat()方法
*/
public
class Cat extends Animal {
@Override
public
void eat() {
System.out.println("猫吃鱼");
}
}
/*****************************************************/
/*
* Dog类继承自Animal父类重写eat()方法
*/
public
class Dog extends Animal {
@Override
public
void eat() {
System.out.println("狗吃骨头");
}
}
/*****************************************************/
/*
* 工厂类,用于生产各个类的实例化对象
*/
public
class AnimalFactory {
public
static Animal createAnimal(String type) {
if ("dog".equals(type)) {
return
new Dog();
} else
if ("cat".equals(type)) {
return
new Cat();
} else {
return
null;
}
}
}
/*****************************************************/
/*
* 测试类
*/
public
class Test {
public
static void main(String[]
args) {
//获取Dog类的实例,调用eat()方法
Animal a=AnimalFactory.createAnimal("dog");
a.eat();
//获取Cat类的实例,调用eat()方法
a=AnimalFactory.createAnimal("cat");
a.eat();
}
}
(2)工厂方法模式
简单工厂模式,若需要添加新动物,比如Pig,需要改动代码这不符合开闭原则,所以出现了工厂方法模式
为每个实体新建一个工厂类,添加新动物,只需新添加一个PigFactory即可
不需改动其他代码,拓展性,维护性更好
Animal
|--Dog
|--Cat
|--Pig
...
AnimalFactory
|--DogFactory
|--CatFactory
|--PigFactory
...
代码体现
/** 顶层父类Animal,所有Animal都有eat()这个方法
*/
public
abstract class Animal {
public
abstract void eat();
}
/*****************************************************/
/*
* Cat类继承自Animal父类重写eat()方法
*/
public
class Cat extends Animal {
13fc0
@Override
public
void eat() {
System.out.println("猫吃鱼");
}
}
/*****************************************************/
/*
* Dog类继承自Animal父类重写eat()方法
*/
public
class Dog extends Animal {
@Override
public
void eat() {
System.out.println("狗吃骨头");
}
}
/*****************************************************/
/*
* 工厂类顶层父类,定义了一个抽象方法creatAnimal
* 子类需重写此方法
*/
public
abstract class AnimalFactory {
public
abstract Animal creatAnimal();
}
/*****************************************************/
/*
* Cat工厂类,继承自AnimalFactory父类
* 重写了creatAnimal方法,返回一个Cat类实例
*/
public
class CatFactory extends AnimalFactory {
@Override
public Animal creatAnimal() {
return
new Cat();
}
}
/*****************************************************/
/*
* Dog工厂类,继承自AnimalFactory父类
* 重写了creatAnimal方法,返回一个Dog类实例
*/
public
class DogFactory extends AnimalFactory {
@Override
public Animal creatAnimal() {
return
new Dog();
}
}
/*****************************************************/
/*
* 工厂方法模式测试类
*/
public
class Test {
public
static void main(String[]
args) {
//实例化Dog工厂
AnimalFactory af=new DogFactory();
//获取Dog类实例
Animal a=af.creatAnimal();
//调用方法
a.eat();
//实例化Cat工厂
af=new CatFactory();
//获取Cat类实例
a=af.creatAnimal();
//调用方法
a.eat();
}
}
2.单例模式
分为懒汉式和饿汉式单一实例模式(唯一实例模式)
在内存中,某一个类只有一个实例存在
eg:windows打印服务
网站访问统计
线程池
思路:
1.构造方法私有,使外界不能随意创建对象
2.提供私有的、静态的当前类的实例,并且实例化
3.对外提供公共的获取方法,返回实例化的当前类的实例变量
(1)饿汉式
类加载就创建对象开发时采用这种方式,更方便
代码体现
/** 饿汉式——类一加载就创建对象
*/
public
class Student {
// 把构造方法私有,不让外界随意创建
private Student() {
}
// 类本身要创建一个对象
// 由于静态只能访问静态,所以对象加静态
// 为了不让外界通过类名直接访问成员变量,所以加私有
private
static Student s =
new Student();
// 提供公共的方法让外界使用
// 为了让外界能够使用类名访问该方法,需要对方法加静态
public
static Student getStudent() {
return
s;
}
public
void show() {
System.out.println("单例模式——饿汉式");
}
}
/*****************************************************/
/*
* 测试类
*/
public
class Test {
public
static void main(String[]
args) {
//获取Student对象的实例
Student s1=Student.getStudent();
Student s2=Student.getStudent();
//返回true,说明指向同一个对象
System.out.println(s1==s2);
s1.show();
s2.show();
}
}
(2)懒汉式
什么时候用,就什么时候创建面试时采用这种方式
延迟加载,节省内存,但是存在线程安全问题,所以必须加锁
代码体现
/** 懒汉式——用到的时候才创建
*/
public
class Teacher {
//私有化构造方法,防止被实例化
private Teacher() {
}
private
static Teacher t =
null;
// t1 t2 t3 3个线程进来
// 如果t是null的时候,才创建对象,会出现问题(3个同时创建了对象)
// 所以这种方式必须加锁synchronized
public
synchronized static Teacher getTeacher() {
if (t ==
null) {
t =
new Teacher();
}
return
t;
}
public
void show() {
System.out.println("单例模式——懒汉式");
}
}
/*****************************************************/
/*
* 测试类
*/
public
class Test {
public
static void main(String[]
args) {
//获取Teacher对象的实例
Teacher t1=Teacher.getTeacher();
Teacher t2=Teacher.getTeacher();
//返回true,说明指向同一个对象
System.out.println(t1==t2);
//调用方法
t1.show();
t2.show();
}
}
3.装饰模式
产生原因:最初,手机具备打电话的功能
按照正常的做法,应该将手机类设计出来,并给出一个打电话的功能。
随着发展,人的需求在变化,假设现在需要在打电话前听到彩铃,那么通过
继承就可以具备父亲打电话的功能,还可以在新手机上添加彩铃功能
继续发展,需求又变了,希望在打电话之前可以播放广告
需求继续改变,想先要有彩铃,接着打电话,最后放广告
需求还可以继续发生变化,虽然使用继承可以解决这些问题,但是,将来一
旦某个父类发生改变,依赖这个父类的所有子类都会受到影响
由于通过长时间的积累,继承体系会异常庞大,父类的改动会影响子类的功
能,且通过继承得到的功能不好控制
设计模式由此产生,用以代替这种模式
装饰模式:对类原有的功能进行修饰或者扩充
A.被装饰的抽象事物Phone
B.具体事物PhoneImpl
实现Phone接口,具体的实现类
C.装饰类PhoneDecorate
实现Phone接口,调用实现
privatePhone phone;
publicPhoneDecorate(Phone phone) {
this.phone = phone;
}
@Override
publicvoid call() {
this.phone.call();// 具体的手机打电话功能
}
当功能需要扩展时
要有彩铃:
具有彩铃功能的装饰类
要有广告:
具有广告功能的装饰类
...
Phone(接口)
|--PhoneImpl(具体实现类)
|--PhoneDecorate(抽象类)
|--ColorPhoneDecorate(具体装饰类)
|--GuanggaoPhoneDecorate(具体装饰类)
代码体现
/** 被装饰的事物Phone
*/
public
interface Phone {
//电话都具有的功能,打电话
public
abstract void call();
}
/*****************************************************/
/*
* 实现类,实现Phone接口
*/
public
class PhoneImpl implements Phone {
//重写了打电话这个方法
@Override
public
void call() {
System.out.println("打电话");
}
}
/*****************************************************/
/*
* 装饰类PhoneDecorate,实现Phone接口
*/
public
abstract class PhoneDecorate
implements Phone {
private Phone
phone;
public PhoneDecorate(Phone
phone){
this.phone=phone;
}
@Override
public
void call() {
this.phone.call();
}
}
/*****************************************************/
/*
* 具体装饰类,具有彩铃功能的装饰类
* 继承自基本装饰类PhoneDecorate
* 重写了打电话call()方法
*/
public
class ColorPhoneDecorate extends PhoneDecorate {
public ColorPhoneDecorate(Phone
phone) {
super(phone);
}
@Override
public
void call() {
System.out.println("播放彩铃");
super.call();
}
}
/*****************************************************/
/*
* 具体装饰类,具有播放广告功能的装饰类
* 继承自基本装饰类PhoneDecorate
* 重写了打电话call()方法
*/
public
class GuanggaoPhoneDecorate extends PhoneDecorate {
public GuanggaoPhoneDecorate(Phone
phone) {
super(phone);
}
@Override
public
void call() {
super.call();
System.out.println("播放广告");
}
}
/*****************************************************/
/*
* 测试类
*/
public
class Test {
public
static void main(String[]
args) {
//实例化Phone的子类
Phone p=new PhoneImpl();
p.call();
System.out.println("------------");
//实例化彩铃功能的装饰类对象
PhoneDecorate pd=new ColorPhoneDecorate(p);
pd.call();
System.out.println("------------");
//实例化播放广告功能的装饰类对象
pd=new GuanggaoPhoneDecorate(p);
pd.call();
System.out.println("------------");
//添加新功能,播放彩铃-打电话-放广告
//不必再新定义一个装饰类,而是采用这种方式实现,简化代码
pd=new GuanggaoPhoneDecorate(new
ColorPhoneDecorate(p));
pd.call();
System.out.println("------------");
}
}
4.模板模式
抽取共性方法,封闭封装,降低耦合性模板类是抽象类,具体实现由继承了模板的子类决定
代码体现1——打印功能
/** 定义了一个打印的模板类
*/
public
abstract class PrintTemple {
public
abstract void printHead();
public
abstract void printBody();
public
abstract void printBottom();
public
void print() {
printHead();
printBody();
printBottom();
}
}
/*****************************************************/
/*
* 继承模板的一种实现类
* 重写了模板中的具体实现方法:printHead、printBody、printBottom
*/
public
class PrintModel1 extends PrintTemple {
@Override
public
void printHead() {
System.out.println("采用第一种方式打印头");
}
@Override
public
void printBody() {
System.out.println("采用第一种方式打印中间");
}
@Override
public
void printBottom() {
System.out.println("采用第一种方式打印尾");
}
}
/*****************************************************/
/*
* 测试类
*/
public
class Test {
public
static void main(String[]
args) {
//实例化模板的子类对象
PrintTemple pm=new PrintModel1();
//调用打印方法
pm.print();
}
}
代码体现2——计算一个功能的运行时间,以模板模式体现
/** 定义一个模板类用于计算function()执行完毕所需时间
*/
public
abstract class Template {
public
long getTime() throws Exception {
//获取方法执行前,系统的时间
long
start = System.currentTimeMillis();
//方法执行
function();
//获取方法执行结束后,系统的时间
long
end = System.currentTimeMillis();
//返回耗时
return
end-start;
}
//具体方法,由子类实现
public
abstract void function();
}
/*****************************************************/
/*
* 继承模板类,要测试的功能为:复制一个mp3文件到当前路径下所需时间
*/
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class TemplateIODemo extends Template {
//重写要执行的具体方法
@Override
public voidfunction() {
try{
FileInputStreamfis = new FileInputStream("D:\\test.mp3");
FileOutputStreamfos = new FileOutputStream("copy.mp3");
int by = 0;
while ((by =fis.read()) != -1) {
fos.write(by);
}
fis.close();
fos.close();
}
catch(Exceptione){
e.printStackTrace();
}
}
}
/*****************************************************/
/*
* 测试类
*/
public
class Test {
public
static void main(String[]
args) throws Exception {
//实例化子类对象
TemplateIODemo tio=new TemplateIODemo();
//获取执行耗时
long
time=tio.getTime();
//打印时间
System.out.println("复制共耗时间:"+time+"毫秒");
}
}
相关文章推荐
- [黑马程序员][OC]代理设计模式
- 黑马程序员--单例设计模式
- 黑马程序员_Java基础_装饰设计模式
- 黑马程序员_单例设计模式
- 黑马程序员 java学习笔记3-IO流之字节流与装饰设计模式
- 黑马程序员—— 4,二维数组,面向对象,制作帮助文档,静态代码块,构造代码块,构造函数,单例设计模式
- 黑马程序员————单例设计模式、线程间的通信等等
- 黑马程序员--懒汉式和饿汉式单例设计模式
- 黑马程序员 单例设计模式
- 【黑马程序员】多线程,设计模式——Java复习笔记
- 黑马程序员——单例设计模式
- 【黑马程序员】java中-------------------单例设计模式
- 黑马程序员 单例设计模式
- 黑马程序员------装饰设计模式
- 黑马程序员--单例设计模式、抽象、继承
- 黑马程序员——JAVA基础之装饰设计模式
- 黑马程序员——设计模式——建造者模式
- 黑马程序员--java--两种设计模式
- 黑马程序员—— 装饰设计模式
- [黑马程序员]第五篇:设计模式