单例模式是一种常用的设计模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在,整个系统只能使用一个对象实例。这样做的优点是不会频繁地创建和销毁对象,浪费资源。通常在IO操作、数据库连接或者Redis连接等场景下使用。
// 1、普通单例模式:项目一启动就初始化,不管之后用没用到。
class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
// 2、延迟加载单例模式:在实际使用到的时候才去初始化,避免浪费。
class SingletonLazy {
private static SingletonLazy instance;
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
// 3、线程安全的单例模式:通过加锁控制,保证在多线程调用时保障只有一个实例化对象。
class SingletonLazy {
private static SingletonLazy instance;
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
简单工厂模式又叫静态工厂方法模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。比如,一台咖啡机就可以理解为一个工厂模式,你只需要按下想喝的咖啡品类的按钮(摩卡或拿铁),它就会给你生产一杯相应的咖啡,你不需要管它内部的具体实现,只要告诉它你的需求即可。简单工厂模式中包含的角色及其相应的职责如下:
简单工厂模式的优点有 :
缺点有:
// 简单工厂模式示例代码
package MyTest;
// 定义动物的接口
interface Animal {
public void say(); // 说话方法
}
class Cat implements Animal {
@Override
public void say() {
System. out .println("我是猫咪,喵呜!" );
}
}
class Dog implements Animal {
@Override
public void say() {
System. out .println("我是小狗,汪汪!" );
}
}
// 定义工厂类
class Factory {
public static Animal getInstance(String className) {
Animal a = null ; // 定义接口对象
if ("Cat" .equals(className)) {
a = new Cat(); // 通过Cat子类实例化接口
}
if ("Dog" .equals(className)) {
a = new Dog(); // 通过Dog子类实例化接口
}
return a ;
}
}
public class FactoryDemo {
public static void main(String[] args) {
Animal cat = null ;
cat = Factory. getInstance("Cat");
Animal dog = null ;
dog = Factory. getInstance("Dog");
cat.say();
dog.say();
}
}
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式不再只由一个工厂类决定哪一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。它的具体组成有以下几部分:
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力,而且这样使得结构变得灵活起来。当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。
// 工厂方法模式示例
package MyTest;
// 抽象产品角色
interface Moveable {
void run();
}
// 具体产品角色
class Plane implements Moveable {
@Override
public void run() {
System. out .println("plane...." );
}
}
class Broom implements Moveable {
@Override
public void run() {
System. out .println("broom....." );
}
}
// 抽象工厂角色
abstract class VehicleFactory {
abstract Moveable create();
}
// 具体工厂角色
class PlaneFactory extends VehicleFactory{
public Moveable create() {
return new Plane();
}
}
class BroomFactory extends VehicleFactory{
public Moveable create() {
return new Broom();
}
}
public class FactoryDemo {
public static void main(String[] args) {
VehicleFactory factory = new BroomFactory();
Moveable m = factory.create();
m.run();
}
}
抽象工厂模式提供一个创建一系列相关或依赖对象的接口,无需指定具体类。在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而构成一个或多个产品族(Product Family)。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。
// 抽象工厂模式示例
package MyTest;
// 抽象产品
abstract class Vehicle{
public abstract void run();
}
// 具体产品
class Bike extends Vehicle{
@Override
public void run() {
System. out .println("bike run..." );
}
}
class Weapon{
public void shoot(){
System. out .println("weapon shoot..." );
}
}
class Food{
public void getName(){
System. out .println("food..." );
}
}
//抽象工厂类
abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Weapon createWeapon();
public abstract Food createFood();
}
//具体工厂类
class DefaultFactory extends AbstractFactory{
@Override
public Vehicle createVehicle() {
return new Bike();
}
@Override
public Weapon createWeapon() {
return new Weapon();
}
@Override
public Food createFood() {
return new Food();
}
}
//测试类
public class FactoryDemo {
public static void main(String[] args) {
AbstractFactory f = new DefaultFactory();
Vehicle v = f.createVehicle();
v.run();
Weapon w = f.createWeapon();
w.shoot();
Food a = f.createFood();
a.getName();
}
}
观察者模式是定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式,它有以下优点 :
缺点如下:
// 观察者模式示例
// 观察者(消息接收方)
interface Observer {
public void update(String message);
}
/*
* 具体的观察者(消息接收方)
*/
class ConcrereObserver implements Observer {
private String name;
public ConcrereObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + ":" + message);
}
}
/*
* 被观察者(消息发布方)
*/
interface Subject {
// 增加订阅者
public void attach(Observer observer);
// 删除订阅者
public void detach(Observer observer);
// 通知订阅者更新消息
public void notify(String message);
}
/*
* 具体被观察者(消息发布方)
*/
class ConcreteSubject implements Subject {
// 订阅者列表
private List<Observer> list = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
list.add(observer);
}
@Override
public void detach(Observer observer) {
list.remove(observer);
}
@Override
public void notify(String message) {
for (Observer observer : list) {
observer.update(message);
}
}
}
public class ObserverTest {
public static void main(String[] args) {
// 定义发布者
ConcreteSubject concreteSubject = new ConcreteSubject();
// 定义订阅者
ConcrereObserver concrereObserver = new ConcrereObserver("老王");
ConcrereObserver concrereObserver2 = new ConcrereObserver("Java");
// 添加订阅
concreteSubject.attach(concrereObserver);
concreteSubject.attach(concrereObserver2);
// 发布信息
concreteSubject.notify("更新了");
}
}
装饰器模式是指动态地给一个对象增加一些额外的功能,同时又不改变其结构。装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
// 装饰器模式示例
/**
* 咖啡接口
*/
interface Coffee {
String getDescription();
double getCost();
}
/**
* 黑咖啡
*/
class BlackCoffee implements Coffee {
@Override
public String getDescription() {
return "黑咖啡";
}
@Override
public double getCost() {
return 2.0;
}
}
/**
* 咖啡装饰器抽象类
*/
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getDescription() {
return coffee.getDescription();
}
@Override
public double getCost() {
return coffee.getCost();
}
}
/**
* 糖装饰器
*/
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", 加糖";
}
@Override
public double getCost() {
return super.getCost() + 0.3;
}
}
/**
* 奶装饰器
*/
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", 加牛奶";
}
@Override
public double getCost() {
return super.getCost() + 0.5;
}
}
public class Main {
public static void main(String[] args) {
// 订一杯黑咖啡
Coffee coffee = new BlackCoffee();
System.out.println("订单:" + coffee.getDescription());
System.out.println("总价:" + coffee.getCost());
// 加牛奶
coffee = new MilkDecorator(coffee);
System.out.println("订单:" + coffee.getDescription());
System.out.println("总价:" + coffee.getCost());
// 再加糖
coffee = new SugarDecorator(coffee);
System.out.println("订单:" + coffee.getDescription());
System.out.println("总价:" + coffee.getCost());
}
}
模板方法模式是指定义一个模板结构,将具体内容延迟到子类去实现,它有以下优点 :
// 模板方法模式示例
// 抽象模板
public abstract class AbstractCook {
public final void doCook(){
openFire();
cooking();
closeFire();
}
protected void openFire() {
System.out.println("点火,开始做菜了");
}
// 具体菜品的烹饪方式不一样,留给子类去实现
protected abstract void cooking();
protected void closedFire() {
System.out.println("关火,菜出锅了");
}
}
// 具体子类
public class cookFish extends AbstractCook {
@Override
protected void cooking() {
System.out.println("一份鱼!");
}
}
public class cookRice extends AbstractCook {
@Override
protected void cooking() {
System.out.println("一份饭!");
}
}
public class TemplateMethodPatternTest {
public static void main(String[] args) {
AbstractCook fish = new cookFish();
fish.doCook();
System.out.println("===========");
FryRice rice = new cookRice();
fryRice.doCook();
}
}
代理模式是给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
优点 :
缺点 :
代理模式可分为静态代理(Static Proxy)、动态代理(Dynamic Proxy)和 CGLIB代理(Code Generation Library Proxy)。
静态代理是在代码编译阶段就已经生成了代理类,代理类需要实现与目标对象相同的接口。它可以在不修改目标对象的前提下对目标对象的方法进行增强,但是需要为每个目标对象创建一个代理类,导致系统中类的数量增加,维护成本较高。
// 静态代理示例
// 抽象接口
public interface Service {
void performOperation();
}
// 目标对象
public class RealService implements Service {
public void performOperation() {
System.out.println("Performing operation in RealService");
}
}
// 代理对象
public class ServiceProxy implements Service {
private RealService realService;
public ServiceProxy(RealService realService) {
this.realService = realService;
}
public void performOperation() {
System.out.println("Proxy: Before operation");
realService.performOperation();
System.out.println("Proxy: After operation");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealService realService = new RealService();
Service proxy = new ServiceProxy(realService);
proxy.performOperation();
}
}
动态代理是在程序运行时,通过反射机制动态生成的代理类。Java提供了 java.lang.reflect.Proxy 类来实现动态代理。它的优点有:
但是由于使用了反射机制,性能相对静态代理略低。
// 动态代理示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 抽象接口
public interface Service {
void performOperation();
}
// 目标对象
public class RealService implements Service {
public void performOperation() {
System.out.println("Performing operation in RealService");
}
}
// 动态代理处理器
public class ServiceInvocationHandler implements InvocationHandler {
private Object target;
public ServiceInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxy: Before operation");
Object result = method.invoke(target, args);
System.out.println("Proxy: After operation");
return result;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealService realService = new RealService();
ServiceInvocationHandler handler = new ServiceInvocationHandler(realService);
Service proxy = (Service) Proxy.newProxyInstance(realService.getClass().getClassLoader(),
new Class<?>[]{Service.class},
handler);
proxy.performOperation();
}
}
CGLIB代理是通过继承目标对象的方式来创建代理类。它是第三方库(如Spring AOP)常用的一种代理方式,适用于没有实现接口的类。CGLIB代理不需要目标对象实现接口,可以代理任何类。由于采用了继承的方式,所以需要注意目标类不能是 final 类,代理类也不能是 final 方法。相对于 JDK 的动态代理,CGLIB代理的性能较高,但由于使用了字节码生成技术,可能会增加复杂性。
// CGLIB代理示例
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// 目标对象
public class RealService {
public void performOperation() {
System.out.println("Performing operation in RealService");
}
}
// CGLIB代理
public class CglibProxy implements MethodInterceptor {
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Proxy: Before operation");
Object result = proxy.invokeSuper(obj, args);
System.out.println("Proxy: After operation");
return result;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealService realService = new RealService();
CglibProxy proxy = new CglibProxy(realService);
RealService proxyService = (RealService) proxy.createProxy();
proxyService.performOperation();
}
}
策略模式是指定义一系列算法,将每个算法都封装起来,并且使他们之间可以相互替换。它遵循了开闭原则,扩展性良好,但随着策略的增加,对外暴露的也会越来越多。
// 策略模式示例
/*
* 声明旅行
*/
interface ITrip {
void going();
}
class Bike implements ITrip {
@Override
public void going() {
System.out.println("骑自行车");
}
}
class Drive implements ITrip {
@Override
public void going() {
System.out.println("开车");
}
}
/*
* 定义出行类
*/
class Trip {
private ITrip trip;
public Trip(ITrip trip) {
this.trip = trip;
}
public void doTrip() {
this.trip.going();
}
}
public class StrategyTest {
public static void main(String[] args) {
Trip trip = new Trip(new Bike());
trip.doTrip();
}
}
适配器模式是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作。它灵活性好,不会破坏原有的系统。但是如果过多地使用适配器,容易使代码结构混乱(如明明看到调用的是 A 接口,内部调用的却是 B 接口的实现)。
// 适配器模式示例
/*
* 传统的充电线 MicroUSB
*/
interface MicroUSB {
void charger();
}
/*
* TypeC 充电口
*/
interface ITypeC {
void charger();
}
class TypeC implements ITypeC {
@Override
public void charger() {
System.out.println("TypeC 充电");
}
}
/*
* 适配器
*/
class AdapterMicroUSB implements MicroUSB {
private TypeC typeC;
public AdapterMicroUSB(TypeC typeC) {
this.typeC = typeC;
}
@Override
public void charger() {
typeC.charger();
}
}
public class AdapterTest {
public static void main(String[] args) {
TypeC typeC = new TypeC();
MicroUSB microUSB = new AdapterMicroUSB(typeC);
microUSB.charger();
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。