设计模式概述和分类
(1)设计模式概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编写、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰。
(2)设计模式分类
- 创建型模式(创建对象的): 单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
- 行为型模式(对象的功能): 适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
- 结构型模式(对象的组成): 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。
1.简单工厂模式
(1)概述
又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例。
(2)优点
- 使用静态工厂模式的优点是实现责任的分割,该模式的核心是工厂类,工厂类含有必要的选择逻辑,可以决定什么时候创建哪一个产品的实例。
- 而客户端则免去直接创建产品的责任,而仅仅是消费产品。也就是说静态工厂模式在不改变客户端代码的情况可以动态的增加产品。
(3)缺点
这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护。
(4)代码演示
package com.设计模式.简单工厂模式;
public class MyDemo {
public static void main(String[] args) {
//定义一个工厂类来负责创建一些类的实例
Animal cat = AnimalFactory.getAnimal("cat");
cat.eat();
Animal dog = AnimalFactory.getAnimal("dog");
dog.eat();
}
}
class AnimalFactory{
private AnimalFactory() {
}
public static Animal getAnimal(String name){
if("cat".equals(name)){
return new Cat();
}else if ("dog".equals(name)){
return new Dog();
}else{
return null;
}
}
}
abstract class Animal{
abstract void eat();
}
class Dog extends Animal{
@Override
void eat() {
System.out.println("狗吃肉");
}
}
class Cat extends Animal{
@Override
void eat() {
System.out.println("猫吃鱼");
}
}
2.工厂方法模式
(1)概述
工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。
(2)优点
客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新的对象的添加,只需要添加一个具体的类和具体的工厂类即可,不影响已有的代码,后期i维护容易,增强了系统的扩展性。
(3)缺点
需要额外的编写代码,增加了工作量。
(4)代码演示
package com.设计模式.工厂模式;
public class MyDemo {
public static void main(String[] args) {
Animal animal = new DogFactory().creatAnimal();
animal.eat();
Animal animal1 = new CatFactory().creatAnimal();
animal1.eat();
}
}
interface AnimalFactory{
Animal creatAnimal();
}
class DogFactory implements AnimalFactory{
@Override
public Animal creatAnimal() {
return new Dog();
}
}
class CatFactory implements AnimalFactory{
@Override
public Animal creatAnimal() {
return new Cat();
}
}
abstract class Animal{
abstract void eat();
}
class Dog extends Animal{
@Override
void eat() {
System.out.println("狗吃肉");
}
}
class Cat extends Animal{
@Override
void eat() {
System.out.println("猫吃鱼");
}
}
3.单例模式
(1)概述
单例对象的类只能允许一个实例存在。
(2)应用场景
- 在我们的windows桌面上,我们打开了一个回收站,当我们试图再次打开一个新的回收站时,Windows系统并不会为你弹出一个新的回收站窗口。,也就是说在整个系统运行的过程中,系统只维护一个回收站的实例。这就是一个典型的单例模式运用。
- 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
应用程序不能创建自己的 Runtime 类实例。
(3)优点
- 在内存中只有一个对象,节省内存空间;
- 避免频繁的创建销毁对象,可以提高性能;
- 避免对共享资源的多重占用,简化访问;
- 为整个系统提供一个全局访问点。
(4)缺点
- 不适用于变化频繁的对象;
- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
- 如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;
(5)饿汉式(开发中)
package com.设计模式.单例模式;
public class 懒汉式 {
public static void main(String[] args) {
Student student = Student.getStudent();
Student student1 = Student.getStudent();
System.out.println(student == student1);
}
}
class Student{
static Student student=new Student();//一加载进内存,就创建一个该类的对象
private Student() {//私有构造,让外界不能创建该类的一个实例
}
public static Student getStudent(){//提供一个静态方法,返回该类的一个实例
return student;
}
}
(3)懒汉式(面试中)
package com.设计模式.单例模式;
public class 饿汉式 {
public static void main(String[] args) {
//饿汉式体现了一种延迟加载的思想,你要用这个对象了我再去创建
Teacher teacher = Teacher.getTeacher();
Teacher teacher1 = Teacher.getTeacher();
System.out.println(teacher == teacher1);
}
}
class Teacher{
//定义一个teacher对象
private static Teacher teacher=null;
//私有化构造
private Teacher() {
}
//提供公共的静态方法,并且保证多线程情况下保证单例
public synchronized static Teacher getTeacher(){
if(teacher==null){
teacher=new Teacher();
}
return teacher;
}
}
4.模板设计模式
(1)概述
模板设计模式就是定义一个算法的骨架,将具体的算法延迟到子类中来实现。
(2)优点
使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求。
(3)缺点
如果算法骨架有修改的话,则需要修改抽象类。
(4)代码演示
package com.设计模式.模板设计模式;
public class Demo {
public static void main(String[] args) {
Testclass testclass = new Testclass();
testclass.testhaoshi();
}
}
class Testclass extends Test{
@Override
void testhaoshi() {
//for循环的算法
for (int i = 0; i < 1000; i++) {
System.out.println("模板设计模式");
}
}
}
abstract class Test{
public void testTime(){
long start = System.currentTimeMillis();
//测试for循环的耗时
testhaoshi();
long end = System.currentTimeMillis();
System.out.println("耗费时间为"+(end - start));
}
abstract void testhaoshi();
}
5.装饰模式
(1)概述
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。是继承的替代方案。
(2)优点
使用装饰模式,可以提供比继承更灵活的扩展对象的功能,它可以动态的添加对象的功能,并且可以随意的组合这些功能。
(3)缺点
正因为可以随意组合,所以就可能出现一些不合理的逻辑。
(4)代码演示
package com.设计模式;
public class Demo {
public static void main(String[] args) {
iPhone iPhone = new iPhone();
iPhone.call();
//当要给手机增加新功能时,我们定义一个包装类
//给手机增加一个听歌功能
Musicphone musicphone = new Musicphone(new iPhone());
musicphone.call();
//IO流用的就是包装者设计模式
//new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
}
}
class Musicphone extends BZphone{
public Musicphone(Phone phone) {
super(phone);
}
@Override
public void call() {
super.call();
System.out.println("听歌");
}
}
class BZphone implements Phone{
//把你要包装的手机传过来
Phone phone;
public BZphone(Phone phone) {
this.phone=phone;
}
@Override
public void call() {
phone.call();
}
}
class iPhone implements Phone{
@Override
public void call() {
System.out.println("打电话");
}
}
interface Phone{
void call();
}
6.观察者模式
(1)概述
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
(2)代码演示
案例:找猎头找工作
工作类
package com.设计模式.观察者模式;
public class Job {
public String name;
public double mmoney;
public Job(String name, double mmoney) {
this.name = name;
this.mmoney = mmoney;
}
}
找工作类
package com.设计模式.观察者模式;
public class Workman {
public String name;
public int age;
public Workman(String name, int age) {
this.name = name;
this.age = age;
}
}
猎头类
package com.设计模式.观察者模式;
import java.util.ArrayList;
public class LieTou {
private ArrayList<Workman> work=new ArrayList<Workman>();//定义一个集合存储求职者信息
private ArrayList<Job> jobs=new ArrayList<Job>();//存储职位信息
//求职者注册的方法
public void addMan(Workman workman ){
work.add(workman);
}
//添加工作的方法
public void addJob(Job job){
jobs.add(job);
//通知求职者有工作
Notice(job);
}
private void Notice(Job job) {
for (Workman workman : work) {
System.out.println(workman.name +"你好,有工作"+ job.name + job.mmoney);
}
}
//注销用户
public void remove(Workman workman){
work.remove(workman);
}
}
测试类
package com.设计模式.观察者模式;
public class MyTest {
public static void main(String[] args) {
Workman man1 = new Workman("张三", 23);
Workman man2 = new Workman("李四", 24);
Job job = new Job("Java后台开发", 9999.0);
LieTou lieTou = new LieTou();
lieTou.addMan(man1);
lieTou.addMan(man2);
lieTou.addJob(job);
}
}