23种设计模式-----创建型模式、结构型模式
一、创建型模式(都是用来帮助创建对象的)
1.单例模式
- 作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
- 应用:Windows的任务管理器、回收站;项目中读取配置文件的类;网站的计数器;应用程序的日志应用;数据库连接池;操作系统的文件系统;Application;Spring中的bean;Servlet;spring MVC框架/struts1框架中的控制器对象
- 选用:占用资源小、不需要延时加载--------枚举-->饿汉 占用资源大 、需要延时 -------------- 静态内部-->懒汉
- 实现方式:
1.饿汉式(线程安全,调用效率高,不能延时加载)
public class SingLetonDemo01 { //类初始化时,立即加载这个对象。加载类时,天然的线程安全 private static SingLetonDemo01 sld = new SingLetonDemo01();
//构造器私有化 private SingLetonDemo01() { } //方法没有同步,调用效率高 public static SingLetonDemo01 getsld() { return sld; } }
2.懒汉式(线程安全,调用效率不高,可以延时加载,并发效率低)
public class SingLetonDemo02 {
//不初始化,临时加载,使用时再加载 private static SingLetonDemo02 lsd; //构造器私有化 private SingLetonDemo02() { } //方法必须加入同步(有同步,效率低) public static synchronized SingLetonDemo02 getlsd() { if(lsd==null) { lsd = new SingLetonDemo02(); } return lsd; } }
3.双重检测锁式(不安全,不建议使用)
4.静态内部类式(线程安全,调用效率高,可以延时加载,并发效率高)
public class SingLetonDemo03 { private static class SingLetonClassInstance{ private static final SingLetonDemo03 sld = new SingLetonDemo03(); } //私有构造器 private SingLetonDemo03() { } //方法没有同步 public static SingLetonDemo03 getsld() { return SingLetonClassInstance.sld; } }
5.枚举单例(简单,线程安全,调用效率高,不能延时加载)
public enum SingLetonDemo04 { //枚举本身就是单例 sld; //添加需要的操作 public void singletonOperation() { } }
2.工厂模式
实现了创建者和调用者的分离
实例化对象,用工厂方法代替new操作
将选择实现类、创建对象统一管理和控制,从而将调用者跟实现类解耦
1.简单工厂模式
- 用来生产同一等级结构中任意产品(新增产品需要修改代码)
方法一:
public class CarFactory01 { //创建者 public static Car createcar(String type) { if("奥迪".equals(type)) { return new Audi(); }else if("奔驰".equals(type)) { return new Benz(); }else { return null; } } }
方法二:
public class CarFactory02 { //创建者 public static Car createAudi() { return new Audi(); } public static Car createBenz() { return new Benz(); } }
测试:
public class Client01 { //调用者 public static void main(String[] args) { Car c1 = CarFactory01.createcar("奥迪"); Car c2 = CarFactory01.createcar("奔驰"); c1.run(); c2.run(); } }
public class Client02 { //调用者 public static void main(String[] args) { Car c1 = CarFactory02.createAudi(); Car c2 = CarFactory02.createBenz(); c1.run(); c2.run(); } }
2.工厂方法模式
- 用来生产同一等级固定产品(可新增任意产品)
汽车接口
public interface Car { void run(); }
汽车工厂接口
public interface CarFactory { Car createCar(); }
实现类
public class AudiFactory implements CarFactory{ @Override public Car createCar() { return new Audi(); } }
测试
public class Client { public static void main(String[] args) { Car c1 = new AudiFactory().createCar(); Car c2 = new BenzFactory().createCar(); c1.run(); c2.run(); } }
3.抽象工厂模式
用来生产不同产品族的全部产品(不能新增、支持新增产品族)
产品接口一:
public interface Engine { void run(); void start(); } class LuxuryEngine implements Engine{ @Override public void run() { System.out.println("动力强"); } @Override public void start() { System.out.println("启动快"); } } class LowEngine implements Engine{ @Override public void run() { System.out.println("动力弱"); } @Override public void start() { System.out.println("启动慢"); } }
产品接口二:
public interface Seat { void massage(); } class LuxurySeat implements Seat{ @Override public void massage() { System.out.println("自动加热"); } } class LowSeat implements Seat{ @Override public void massage() { System.out.println("无自动加热"); } }
产品接口三:
public interface Tyre { void revolve(); } class LuxuryTyre implements Tyre{ @Override public void revolve() { System.out.println("磨损慢"); } } class LowTyre implements Tyre{ @Override public void revolve() { System.out.println("磨损快"); } }
汽车工厂接口:
public interface CarFactory { Engine createEngine(); Seat createSeat(); Tyre createTyre(); } public class LuxuryCarFactory implements CarFactory{ @Override public Engine createEngine() { return new LuxuryEngine(); } @Override public Seat createSeat() { return new LuxurySeat(); } @Override public Tyre createTyre() { return new LuxuryTyre(); } }
测试:
public class Client { public static void main(String[] args) { CarFactory factory = new LuxuryCarFactory(); Engine e = factory.createEngine(); e.run(); e.start(); } }
4.建造者模式
Builder负责构造、Director负责装配 实现了构建和装配的解耦。
不同的构建器,相同的装配,可以做出不同的对象
相同的构建,不同的装配,也是不同的对象
汽车:
public class Car { private Engine engine;//发动机 private Seat seat;//座椅 private Tyre tyre;//轮胎 public void run() { System.out.println("汽车发动"); } public Engine getEngine() { return engine; } public void setEngine(Engine engine) { this.engine = engine; } public Seat getSeat() { return seat; } public void setSeat(Seat seat) { this.seat = seat; } public Tyre getTyre() { return tyre; } public void setTyre(Tyre tyre) { this.tyre = tyre; } } class Engine { private String name; public Engine(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Seat{ private String name; public Seat(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Tyre{ private String name; public Tyre(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
汽车构建:
public interface CarBuilder { Engine builderEngine(); Seat builderSeat(); Tyre builderTyre(); }
汽车装配:
public interface CarDirector { Car directorCar(); }
Hg牌汽车构建:
public class HgCarBuilder implements CarBuilder{ @Override public Engine builderEngine() { System.out.println("构建Hg牌发动机"); return new Engine("Hg牌发动机"); } @Override public Seat builderSeat() { System.out.println("构建座椅"); return new Seat("Hg牌座椅"); } @Override public Tyre builderTyre() { System.out.println("构建轮胎"); return new Tyre("Hg牌轮胎"); } }
Hg牌汽车装配:
public class HgCarDirector implements CarDirector{ private CarBuilder builder; public HgCarDirector(CarBuilder builder) { this.builder = builder; } @Override public Car directorCar() { Engine e = builder.builderEngine(); Seat s = builder.builderSeat(); Tyre t = builder.builderTyre(); //装配成汽车对象 Car car = new Car(); car.setEngine(e) ; car.setSeat(s); car.setTyre(t); return car; } }
实现:
public class Client { public static void main(String[] args) { CarDirector director = new HgCarDirector(new HgCarBuilder()); Car car = director.directorCar(); System.out.println(car.getEngine().getName()); car.run(); } }
5.原型模式
通过new产生一个对象需要非常复杂的数据准备或访问权限,则可使用。
Cloneable接口和clone方法。
克隆羊接口:
public class Sheep implements Cloneable{ //克隆羊,多利 private String name; private int age; @Override protected Object clone() throws CloneNotSupportedException { return super.clone();//返回Object对象的方法 } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Sheep(String name, int age) { super(); this.name = name; this.age = age; } }
测试浅克隆:
public class Client { public static void main(String[] args) throws Exception { Sheep s1 = new Sheep("羊驼",18); Sheep s2 = (Sheep)s1.clone(); System.out.println(s1.getName()); System.out.println(s1.getAge()); s1.setAge(17); System.out.println(s1.getAge()); System.out.println(s2.getName()); System.out.println(s2.getAge()); } }
二、结构型模式(实现松藕合)
1.适配器模式
- 目标接口(Target):具体或抽象的类,可以是接口
- 适配的类(Adaptee):需要适配的类或适配者类
- 适配器(Adapter):包装一个需要适配的对象,把原接口转换为目标接口
应用于旧系统改造和升级
被适配的类:
public class Adaptee { public void request() { System.out.println("完成请求需要的功能"); } }
适配器:
public class Adapter extends Adaptee implements Target{ @Override public void handleReq() { super.request(); } }
目标接口:
public interface Target { void handleReq(); }
客户端类、测试:
public class Client { public void test(Target t) { t.handleReq(); } public static void main(String[] args) { Client c = new Client(); Target t = new Adapter(); c.test(t); } }
2.桥接模式(bridge)
处理多层继承结构、多维度变化场景,将各个维度设计成独立的继承机构,使各个维度可以独立的扩展在抽象层建立关联
应用于:JDBC、银行日志、奖金计算、OA系统消息处理
销售电脑例子
品牌维度:
public interface Brand { void sale() ; } class Lenovo implements Brand{ @Override public void sale() { System.out.println("销售联想品牌"); } } class Dell implements Brand{ @Override public void sale() { System.out.println("销售戴尔品牌"); } }
电脑类型维度:
public class Computer { protected Brand brand; public Computer(Brand b) { this.brand = b; } public void sale() { brand.sale(); } } class Desktop extends Computer{ public Desktop(Brand b) { super(b); } public void sale() { super.sale(); System.out.println("销售台式机"); } } class Laptop extends Computer{ public Laptop(Brand b) { super(b); } public void sale() { super.sale(); System.out.println("销售笔记本"); } }
测试:
public class Client { public static void main(String[] args) { //销售联想牌笔记本 Computer c = new Laptop(new Lenovo()); c.sale(); } }
3.装饰模式(decorator)
- 抽象构件Component:真实对象和装饰对象有相同的接口
- 具体构件ConcreteComponent:真实对象
- 装饰Decorator:持有一个抽象构件的引用
- 具体装饰ConcreteDecorator:负责给构件对象增加新的东西
汽车实现:
public interface ICar { void move(); } //具体构件(真实对象) class Car implements ICar{ @Override public void move() { System.out.println("普通汽车"); } } //装饰角色 class SuperCar implements ICar{ protected ICar car; public SuperCar(ICar car) { super(); this.car = car; } @Override public void move() { car.move(); } } //具体装饰角色 class FlyCar extends SuperCar{ public FlyCar(ICar car) { super(car); } private void fly() { System.out.println("可以天上飞"); } @Override public void move() { super.move(); fly(); } } //具体装饰 class AICar extends SuperCar{ public AICar(ICar car) { super(car); } private void Auto() { System.out.println("可以自动驾驶"); } @Override public void move() { super.move(); Auto(); } }
测试:
public class Client { public static void main(String[] args) { Car car = new Car(); car.move(); System.out.println("添加飞行功能"); FlyCar flycar = new FlyCar(car); flycar.move(); System.out.println("添加自动驾驶功能"); AICar aicar = new AICar(car); aicar.move(); } }
4.组合模式(composite)
用于处理树形结构,便于统一处理
应用于:操作系统资源管理器、GUI的容器层次图、XML文件解析、OA中组织结构处理、Junit单元测试框架
核心:
- 抽象构件(Component):定义叶子和容器构件的共同点
- 叶子(Leaf)构件:无子节点
- 容器(Composite)构件:有容器特征,包含子节点
public interface Component { void operation(); } //叶子组件 interface Leaf extends Component{ } //容器组件 interface Composite extends Component{ void add(Component c); void remove(Component c); Component getChild(int index); }
5.外观模式
为子系统提供统一的入口。封装子系统的复杂性,便于客户端调用
6.享元模式FlyWeight
存在很多个完全相同或相似的对象。可以通过享元模式节省内存
--享元模式一共享的方式高效地支持大量细粒度对象的重用。
--享元模式对象能 做到共享的关键是区分内部状态和外部状态。
-内部状态:可以共享,不会随环境变化而变化。
-外部状态:不可以共享,会随着环境变化而改变。
模式实现:
- 享元工厂类FlyweightFactory:创建并管理享元对象,享元池一般设计成键值对
- 抽象享元类FlyWeight:接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态
- 具体享元类ConcreteFlyWeight:为内部状态提供成员变量进行存储
- 非共享享元类UnsharedConcreteFlyWeight:不能被共享的子类可以设计为非共享享元类
7.代理模式(proxy pattern)
- 安全代理:屏蔽对真实角色的直接访问
- 远程代理:通过代理类处理远程方法调用
- 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。
静态代理(静态定义代理类):
抽象角色:
public interface Star { //聊天 void talk(); //签合同 void signContract(); //唱歌 void sing(); }
代理:
public class ProxyStar implements Star{ private Star star; public ProxyStar(Star star) { super(); this.star = star; } @Override public void talk() { System.out.println("聊天"); } @Override public void signContract() { System.out.println("签合同"); } @Override public void sing() { star.sing(); } }
真实类:
public class RealStar implements Star{ @Override public void talk() { System.out.println("聊天"); } @Override public void signContract() { System.out.println("签合同"); } @Override public void sing() { System.out.println("陈奕迅唱歌"); } }
测试:
public class Client { public static void main(String[] args) { Star real = new RealStar(); Star proxy = new ProxyStar(real); proxy.talk(); proxy.signContract(); proxy.sing(); } }
动态代理:(动态生成代理类)
- java.lang.reflect.Proxy -->动态生成代理类和对象
- java.lang.reflect.InvocationHandler(处理器接口)--> 通过invoke方法实现对真是角色的代理访问。通过Proxy生成代理类对象时都要指定对应的处理器对象
代理类:
public class StarHandler implements InvocationHandler{ Star realStar; public StarHandler(Star realStar) { super(); this.realStar = realStar; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object object = null; if(method.getName().equals("sing")) { object = method.invoke(realStar, args); } return object; } }
测试:
public class Client { public static void main(String[] args) { StarHandler handler = new StarHandler(new RealStar()); Star proxy = (Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {Star.class}, handler); proxy.sing(); } }