提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
前言
在软件开发中,为了提高软件系统的可维护性和可用性,增加软件的可扩展性和灵活性,开发过程中尽量根据7条原则进行设计,从而提高软件的开发效率、节约软件的开发成本。
提示:以下是本篇文章正文内容,下面案例可供参考
一、设计模式的七大基本原则
- 开闭原则:对扩展开放,对修改关闭。对程序功能进行拓展的时候,不能修改原有的代码;
- 单一职责原则:一个类只负责一个功能领域相对应的职责;
- 里氏替换原则:子类可以扩展父类的功能,但不能修改父类原有的功能。即一个子类不能修改父类原有的方法,只有新增方法;
- 依赖倒置原则:面向接口编程,高层模板与底层模板不应该相互依赖。两者应该依赖于各自的抽象;
- 接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上。每一个类都有自己的接口,而不适用单一的总接口;
- 迪米特法则(最少知识原则):一个软件实体应该尽可能少的与其他实体发生直接相互作用。例:有三个对象A、B、C。A对象要向C对象发送一个信息,那么A对象并不会直接发送C对象,而是先发送给B对象,然后B对象再把信息发送给C对象;
- 合成/聚合复用原则:应该尽可能使用合成、聚合的方式实现代码的复用。不建议使用继承的方式实现代码复用。 继承的缺点:(1)继承破坏了类的封装性。因为继承会将父类的实现细节暴露给子类;(2)子类与父类的耦合度高。当父类修改任何的方法时,子类也要对应进行修改,不利于代码的维护。(3)限制了复用的灵活性。
二、单例模式
什么是单例设计模式:单例模式就是保住在JVM虚拟机内存内一个类只能存在一个实例
以下是单例模式的三种实现方式:
1.饿汉式单例
在加载时就对类进行实例化,占用的内存相对较大
代码如下(示例):
public class Hungry {
private final static Hungry HUNGRY = new Hungry();
private Hungry(){}; //单例模式的重点:对构造器进行私有化
//静态方法调用静态变量
public static Hungry getInstance(){
return HUNGRY;
}
}
2.懒汉式单例
在加载时并不会对类进行实例化,而是在使用的时候进行类的实例化。启动速度快,运行速度相对较慢。
代码如下(示例):
public class Lazy {
private volatile static Lazy LAZY; //加上volatile关键字,防止出现指令重排
private Lazy(){}; //单例模式的重点:对构造器进行私有化
public static Lazy getInstance(){
//双重检测锁模式
if (LAZY == null){
synchronized (Lazy.class){ //加上锁,防止多线程出现并发问题
if (LAZY == null){
//创建对象不是一个原子性操作,可能出现指令重排,需要在属性上加上volatile
LAZY = new Lazy();
}
}
}
return LAZY;
}
}
3.内部类实现方式
代码如下(示例):
public class Hodel {
private Hodel(){} //构造器私有化
public static Hodel getInstance(){
return InnerHodel.HODEL;
}
private static class InnerHodel{ //内部类
private static final Hodel HODEL = new Hodel();
}
}
三、工厂模式
满足创建和使用相分离,即不通过new的方式过去对象实例
1.简单工厂模式
代码如下(示例):
主要是生成同一产品等级的实例
//接口
public interface Cat {
void name();
}
//五菱宏光的车类
public class WulingCat implements Cat{
@Override
public void name() {
System.out.println("五菱宏光");
}
}
//特斯拉的车类
public class TesilaCat implements Cat{
@Override
public void name() {
System.out.println("特斯拉");
}
}
//简单工厂
public class SimpleFactory {
public static Cat getCat(String name){
if (name.equals("五菱")){
return new WulingCat();
}else if (name.equals("特斯拉")){
return new TesilaCat();
}else {
return null;
}
}
}
//用户类,测试
public class Client{
public static void main(String[] args) {
Cat wuLing = SimpleFactory.getCat("五菱");
}
}
2.工厂方法模式
主要是生成同一产品等级的实例
代码如下(示例):
//车接口
public interface Cat {
void name();
}
//五菱宏光类
public class WulingCat implements Cat{
@Override
public void name() {
System.out.println("五菱宏光");
}
}
//特斯拉类
public class TesilaCat implements Cat{
@Override
public void name() {
System.out.println("特斯拉");
}
}
//工厂方法接口
public Interface FactoryMethod{
Cat getCat();
}
//五菱宏光工厂
public class WuLingFactory implements FactoryMethod {
@Override
public Cat getCat(){
return new WuLingCat();
}
}
//特斯拉工厂
public class WuLingFactory implements FactoryMethod {
@Override
public Cat getCat(){
return new TesilaCat();
}
}
//用户类、测试
public class client{
public static void main(String[] args) {
//创建特斯拉工厂
TesilaCatFactory tesilaCatFactory = new TesilaCatFactory();
//有特斯拉工厂获取特斯拉实例
Cat tesilaCat = tesilaCatFactory.getCat();
tesilaCat.name();
}
}
3.抽象工厂
抽象工厂是生成工厂的工厂,即建立工厂实例。主要是生成多种产品族的实例
代码如下(示例):
//手机接口
public interface IIpone {
void name();
}
//路由接口
public Interface IRoute{
void name();
}
//小米手机
public class XiaoMiIpone implements IIpone{
@Override
public void name() {
System.out.println("是小米手机");
}
}
//小米路由
public class XiaoMiRoute implements IRoute{
@Override
public void name() {
System.out.println("小米路由器");
}
}
//华为手机
public class HuaWeiIpone implements IIpone{
@Override
public void name() {
System.out.println("华为手机");
}
}
//华为路由
public class HuaWeiRoute implements IRoute{
@Override
public void name() {
System.out.println("华为路由器");
}
}
//抽象工厂的接口
public interface AbstactFactory {
//手机工厂
IIpone getIpone();
//路由器工厂
IRoute getRoute();
}
//小米工厂
public class XiaoFactory implements AbstactFactory {
@Override
public IIpone getIpone() {
return new XiaoMiIpone();
}
@Override
public IRoute getRoute() {
return new XiaoMiRoute();
}
}
//华为工厂
public class HuaWeiFactory implements AbstactFactory {
@Override
public IIpone getIpone() {
return new HuaWeiIpone();
}
@Override
public IRoute getRoute() {
return new HuaWeiRoute();
}
}
//用户类、测试
public class client{
public static void main(String[] args) {
HuaWeiFactory huaWeiFactory = new HuaWeiFactory();
IIpone ipone = huaWeiFactory.getIpone();
IRoute route = huaWeiFactory.getRoute();
ipone.name();
route.name();
}
}
三、观察者模式
观察者模式也称为发布-订阅模式,是一种对象之间一对多的依赖关系,当一个对象状态发生改变时,其他依赖该对象的对象会收到通知,并自动更新状态。
代码如下(示例):
//借款接口
public interface Borrow{
void brrow(Loans loans);
void notifys();
}
//贷款接口
public interface Loans{
void tackMony();
}
//借款人类
public class DibetMan implements Borrow{
private List<Loans> loansList = new ArrayList<>();
@Override
public void brrow(Loans loans) {
loansList.add(loans);
}
@Override
public void notifys() {
for (Loans loans :
loansList) {
loans.tackMony();
}
}
}
//贷款人类
public class LoansMan implements Loans{
@Override
public void tackMony() {
System.out.println("要钱");
}
}
四、装饰者模式
在不改变原有代码的情况下,动态的给对象增加额外的功能
代码如下(示例):
//机器人接口
public interface Robot {
void dosomeThing();
}
//一代机器人
public class OneRobot implements Robot{
@Override
public void dosomeThing() {
System.out.println("唱歌");
}
}
//二代机器人
public class TowRobot implements Robot{
private Robot robot;
public void setRobot(Robot robot){
this.robot = robot;
}
@Override
public void dosomeThing(){
doMore(); //在一代机器人的基础上新增的功能
robot.dosomeThing(); //一代机器人的功能
}
public void doMore(){
System.out.println("新增的功能");
}
}
五、代理模式
在访问的时候并不会直接去访问真实对象,而是通过代理对象去访问
1.静态代理
需要手动创建代理类,每有一个真实对象(被代理类),就需要手动创建一个代理类。代码量翻倍
//被代理类和代理类的公共接口
public interface IHost {
void rent();
}
//真实对象(被代理类)
public class Host implements IHost{
@Override
public void rent(){
System.out.println("房东出租房子");
}
}
//代理类
public class Proxy implements IHost{
private IHost host;
public void setHost(IHost host){
this.host = host;
}
@Override
public void rent(){
seeHost(); //代理类新增的功能
host.rent();
}
//代理类新增的功能
public void seeHost(){
System.out.println("中介看房");
}
}
//测试类
public class TestDemo {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.setHost(new Host());
proxy.rent();
}
}
2.动态代理
能够自动创建代理类,不需要手动创建代理类。动态代理分为两种:Cglib和Jdk,前者基于类、后者基于接口。动态代理有两个重要的接口(类):Proxy和InvocationHandler。虽然动态代理不需要写代理类,但是需要手动写一个ProxyInvocationHandler(实现InvocationHandler的调用处理程序),并且该类内部聚合代理接口,有可以生成并返回代理类的方法,以及处理代理类实例的方法。
//真实对象接口
public interface Rent {
void rent();
}
//真实对象(被代理类)
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东出租房子");
}
}
//调用处理程序
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
//代理哪一个类就从这里确定的
public void setTarget(Object target) {
this.target = target;
}
//生成并返回代理类
public Object getProxy(){
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHost(); //代理类新增的功能
Object result = method.invoke(target, args);
return result;
}
//代理类新增的功能
public void seeHost(){
System.out.println("看房子");
}
}
//测试
public class Client {
public static void main(String[] args) {
Host host = new Host();
//创建调用处理程序对象
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//传入被代理类,从而确定代理对象
proxyInvocationHandler.setTarget(host);
//获取代理类
Rent proxy = (Rent) proxyInvocationHandler.getProxy();
proxy.rent();
}
}
总结
以上是本人对这几种设计模式的理解以及一些案例,希望对您有所帮助,有错误之处,请批评指正。