设计模式
开闭原则
对修改关闭,对拓展开放
策略模式
在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
代码案例:
Operation 接口
package com.bsj.strategy;
public interface Operation {
public int doOperation(int num1,int num2);
}
Calculator
package com.bsj.strategy;
public class Calculator {
private Operation operation;
public void setOperation(Operation operation) {
this.operation = operation;
}
public int doOperation(int num1, int num2){
return this.operation.doOperation(num1,num2);
}
}
OperationAdd
package com.bsj.strategy;
public class OperationAdd implements Operation{
@Override
public int doOperation(int num1, int num2) {
return num1+num2;
}
}
OperationSub
package com.bsj.strategy;
public class OperationSub implements Operation{
@Override
public int doOperation(int num1, int num2) {
return num1-num2;
}
}
Test
package com.bsj.strategy;
public class Test {
public static void main(String[] args) {
Calculator calculator = new Calculator();
calculator.setOperation(new OperationAdd());
System.out.println(calculator.doOperation(2, 1));
calculator.setOperation(new OperationSub());
System.out.println(calculator.doOperation(2, 1));
}
}
装饰模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
代码案例:
Person接口
package com.bsj.decorator;
public interface Person {
public Double cost();
public void show();
}
XiaoMing
package com.bsj.decorator;
public class XiaoMIng implements Person{
@Override
public Double cost() {
return 0.0;
}
@Override
public void show() {
System.out.println("没穿衣服的小明");
}
}
ClothesDecorator
package com.bsj.decorator;
public abstract class ClothesDecorator implements Person{
protected Person person;
public ClothesDecorator(Person person) {
this.person = person;
}
}
Shirt
package com.bsj.decorator;
public class Shirt extends ClothesDecorator{
public Shirt(Person person) {
super(person);
}
@Override
public Double cost() {
return this.person.cost() + 1000;
}
@Override
public void show() {
this.person.show();
System.out.println("买了一件衬衫,累计消费" + this.cost());
}
}
Trousers
package com.bsj.decorator;
public class Trousers extends ClothesDecorator {
public Trousers(Person person) {
super(person);
}
@Override
public Double cost() {
return this.person.cost() + 800;
}
@Override
public void show() {
this.person.show();
System.out.println("买了一条裤子,累计消费" + this.cost());
}
}
Test
package com.bsj.decorator;
public class Test {
public void show(){
System.out.println("买衣服,花了1000元");
System.out.println("买裤子,花了800元");
System.out.println("买鞋子,花了900元");
}
public static void main(String[] args) {
Person xiaoming = new XiaoMIng();
xiaoming = new Shirt(xiaoming);
xiaoming = new Trousers(xiaoming);
xiaoming.show();
System.out.println("小明共消费" + xiaoming.cost());
}
}
观察者模式
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
代码案例:
Customer
package com.bsj.observer;
public abstract class Customer {
public abstract void update();
}
NewspaperOffice
package com.bsj.observer;
import java.util.ArrayList;
import java.util.List;
public class NewspaperOffice {
private List<Customer> customers = new ArrayList<>();
public void addCustomer(Customer customer){
customers.add(customer);
}
public void notifyAllObservers(){
for (Customer customer : customers) {
customer.update();
}
}
public void newspaper(){
this.notifyAllObservers();
}
}
CustomerA
package com.bsj.observer;
public class CustomerA extends Customer{
@Override
public void update() {
System.out.println("客户A的报纸已送达");
}
}
CustomerB
package com.bsj.observer;
public class CustomerB extends Customer{
@Override
public void update() {
System.out.println("客户B的报纸已送达");
}
}
Test
package com.bsj.observer;
public class Test {
public static void main(String[] args) {
NewspaperOffice newspaperOffice = new NewspaperOffice();
Customer customerA = new CustomerA();
Customer customerB = new CustomerB();
newspaperOffice.addCustomer(customerA);
newspaperOffice.addCustomer(customerB);
newspaperOffice.newspaper();
}
}
单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。
注意:
-
1、单例类只能有一个实例。
-
2、单例类必须自己创建自己的唯一实例。
-
3、单例类必须给所有其他对象提供这一实例。
代码案例:
Single
package com.bsj.singleton;
public class Single {
private volatile static Single instance;
private Single(){
System.out.println("创建了Single对象");
}
public synchronized static Single getInstance(){
if (instance == null){
synchronized (Single.class){
if (instance == null){
instance = new Single();
}
}
}
return instance;
}
}
Test
package com.bsj.singleton;
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
Single.getInstance();
}).start();
}
}
}
工厂模式
Computer接口
package com.bsj.factory;
public interface Computer {
public void show();
}
ComputerFactory
package com.bsj.factory;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
public class ComputerFactory {
public Computer createComputer(String name){
Computer computer = null;
if (name.equals("a")) computer = new ComputerA();
if (name.equals("b")) computer = new ComputerB();
return computer;
}
}
ComputerA
package com.bsj.factory;
public class ComputerA implements Computer{
@Override
public void show() {
System.out.println("生产了A电脑");
}
}
ComputerB
package com.bsj.factory;
public class ComputerB implements Computer{
@Override
public void show() {
System.out.println("生产了B电脑");
}
}
Test
package com.bsj.factory;
public class Test {
public static void main(String[] args) {
ComputerFactory computerFactory = new ComputerFactory();
Computer a = computerFactory.createComputer("a");
Computer b = computerFactory.createComputer("b");
a.show();
b.show();
}
}
适配器模式
将一个接口转换为客户端所期待的接口,从而使两个接口不兼容的类可以在一起工作。例如适配器模式,这个在日常生活中就太普遍了。 例如我们程序员经常遇到的电脑上提供的端口与要插入的接头匹配不上,而我们则可以通过一个中间的适配器将两边连接起来。
代码案例:
MusicPlayer 接口
package com.bsj.adapter;
public interface MusicPlayer {
public void play(String type,String filename);
}
Myplayer
package com.bsj.adapter;
public class MyPlayer {
public void playMp3(String filename){
System.out.println("play mp3:" + filename);
}
public void playWma(String filename){
System.out.println("play wam:" + filename);
}
}
PlayerAdapter
package com.bsj.adapter;
public class PlayerAdapter implements MusicPlayer{
private MyPlayer myPlayer;
public PlayerAdapter() {
this.myPlayer= new MyPlayer();
}
@Override
public void play(String type, String filename) {
if (type.equals("mp3")) this.myPlayer.playMp3(filename);
if (type.equals("wma")) this.myPlayer.playWma(filename);
}
}
Test
package com.bsj.adapter;
public class Test {
public static void main(String[] args) {
MusicPlayer player= new PlayerAdapter();
player.play("mp3","xxx.mp3");
player.play("wma","xxx.wma");
}
}
代理模式
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
考虑生活中一个常见的例子,客户想买房,房东有很多房,提供卖房服务,但房东不会带客户看房,于是客户通过中介买房。
代码案例:
House 接口
package com.bsj.proxy;
public interface House {
public void findHouse();
}
HouseProxy
package com.bsj.proxy;
public class HouseProxy implements House{
private House house;
public HouseProxy(House house) {
this.house = house;
}
@Override
public void findHouse() {
System.out.println("日志:找了一个代理");
this.house.findHouse();
}
}
XiaoMing
package com.bsj.proxy;
public class XiaoMing implements House{
@Override
public void findHouse() {
System.out.println("找房子");
}
}
Test
package com.bsj.proxy;
public class Test {
public static void main(String[] args) {
House house = new XiaoMing();
HouseProxy proxy = new HouseProxy(house);
proxy.findHouse();
}
}
模块方法模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
代码案例:
Cook
package com.bsj.templatemethod;
public abstract class Cook {
public void open(){
System.out.println("打开抽油烟机");
}
public void fire(){
System.out.println("生火");
}
public abstract void doCook();
public void outFire(){
System.out.println("关火");
}
public void close(){
System.out.println("关闭抽油烟机");
}
public final void cook(){ //加上final修改
this.open();
this.fire();
this.doCook();
this.outFire();
this.close();
}
}
CookPotato
package com.bsj.templatemethod;
public class CookPotato extends Cook{
@Override
public void doCook() {
System.out.println("炒土豆丝");
}
}
CookTomato
package com.bsj.templatemethod;
public class CookTomato extends Cook{
@Override
public void doCook() {
System.out.println("西红柿炒鸡蛋");
}
}
Test
package com.bsj.templatemethod;
public class Test {
public static void main(String[] args) {
Cook cook = new CookTomato();
cook.cook();
System.out.println("****************************");
cook = new CookPotato();
cook.cook();
}
}
责任链模式
为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
代码案例:
Post
package com.bsj.responsibility;
public class Post {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
PostHandler
package com.bsj.responsibility;
import javafx.geometry.Pos;
public abstract class PostHandler {
private PostHandler handler;
public void setHandler(PostHandler handler) {
this.handler = handler;
}
public abstract void handlerRequest(Post post);
protected final void next(Post post){
if (this.handler!=null){
this.handler.handlerRequest(post);
}
}
}
AHandler
package com.bsj.responsibility;
public class AHandler extends PostHandler{
@Override
public void handlerRequest(Post post) {
String content = post.getContent();
content = content.replace("广告","**");
post.setContent(content);
System.out.println("过滤广告");
next(post);
}
}
BHandler
package com.bsj.responsibility;
public class BHandler extends PostHandler{
@Override
public void handlerRequest(Post post) {
String content = post.getContent();
content = content.replace("游戏推广","**");
post.setContent(content);
System.out.println("过滤游戏推广");
next(post);
}
}
Test
package com.bsj.responsibility;
public class Test {
public static void main(String[] args) {
PostHandler aHandler = new AHandler();
PostHandler bHandler = new BHandler();
aHandler.setHandler(bHandler);
Post post = new Post();
post.setContent("正常内容,广告,游戏推广");
System.out.println("过滤前的内容:" + post.getContent());
aHandler.handlerRequest(post);
System.out.println("过滤后的内容:" + post.getContent());
}
}
总结
设计模式是一套经过验证的,可复用的解决特定问题的解决方案。它们是软件开发过程中的经验法则,能够帮助开发人员解决设计和实现复杂的软件系统。设计模式可以帮助开发人员遵循最佳实践,提高代码的可读性、可维护性和可扩展性。